Skip to content

Commit 143163e

Browse files
authored
Feature/TLS cert configuration (#1660)
* expose client tls for dls config * expose client tls for dls config (code formatting fixes) * expose client tls for dls config (annotation, default value and formatting fixes) * expose client tls for dls config (HttpExportConfigurationTest changes)
1 parent 0f19a20 commit 143163e

8 files changed

Lines changed: 246 additions & 55 deletions

File tree

android-agent/api/android-agent.api

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ public final class io/opentelemetry/android/agent/OpenTelemetryRumInitializer {
77
public static synthetic fun initialize$default (Landroid/content/Context;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lio/opentelemetry/android/OpenTelemetryRum;
88
}
99

10+
public final class io/opentelemetry/android/agent/connectivity/ClientTlsConnectivity {
11+
public fun <init> ([B[B)V
12+
public final fun getCertificatePem ()[B
13+
public final fun getPrivateKeyPem ()[B
14+
}
15+
1016
public final class io/opentelemetry/android/agent/connectivity/Compression : java/lang/Enum {
1117
public static final field GZIP Lio/opentelemetry/android/agent/connectivity/Compression;
1218
public static final field NONE Lio/opentelemetry/android/agent/connectivity/Compression;
@@ -37,12 +43,14 @@ public final class io/opentelemetry/android/agent/dsl/EndpointConfiguration {
3743
public final class io/opentelemetry/android/agent/dsl/HttpExportConfiguration {
3844
public final fun getBaseHeaders ()Ljava/util/Map;
3945
public final fun getBaseUrl ()Ljava/lang/String;
46+
public final fun getClientTls ()Lio/opentelemetry/android/agent/connectivity/ClientTlsConnectivity;
4047
public final fun getCompression ()Lio/opentelemetry/android/agent/connectivity/Compression;
4148
public final fun getSslContext ()Lio/opentelemetry/android/agent/connectivity/SSLContextConnectivity;
4249
public final fun logs (Lkotlin/jvm/functions/Function1;)V
4350
public final fun metrics (Lkotlin/jvm/functions/Function1;)V
4451
public final fun setBaseHeaders (Ljava/util/Map;)V
4552
public final fun setBaseUrl (Ljava/lang/String;)V
53+
public final fun setClientTls (Lio/opentelemetry/android/agent/connectivity/ClientTlsConnectivity;)V
4654
public final fun setCompression (Lio/opentelemetry/android/agent/connectivity/Compression;)V
4755
public final fun setSslContext (Lio/opentelemetry/android/agent/connectivity/SSLContextConnectivity;)V
4856
public final fun spans (Lkotlin/jvm/functions/Function1;)V

android-agent/src/main/kotlin/io/opentelemetry/android/agent/OpenTelemetryRumInitializer.kt

Lines changed: 50 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import io.opentelemetry.android.Incubating
1212
import io.opentelemetry.android.OpenTelemetryRum
1313
import io.opentelemetry.android.RumBuilder
1414
import io.opentelemetry.android.agent.connectivity.Compression
15+
import io.opentelemetry.android.agent.connectivity.HttpEndpointConnectivity
1516
import io.opentelemetry.android.agent.dsl.OpenTelemetryConfiguration
1617
import io.opentelemetry.android.agent.session.SessionConfig
1718
import io.opentelemetry.android.agent.session.SessionIdTimeoutHandler
@@ -66,42 +67,57 @@ object OpenTelemetryRumInitializer {
6667
.setSessionProvider(createSessionProvider(ctx, cfg))
6768
.setResource(resource)
6869
.setClock(cfg.clock)
69-
.addSpanExporterCustomizer {
70-
OtlpHttpSpanExporter
71-
.builder()
72-
.setEndpoint(spansEndpoint.getUrl())
73-
.setHeaders(spansEndpoint::getHeaders)
74-
.setCompression(spansEndpoint.getCompression().getUpstreamName())
75-
.apply {
76-
spansEndpoint.getSslContext()?.let {
77-
setSslContext(it.sslContext, it.sslX509TrustManager)
78-
}
79-
}.build()
80-
}.addLogRecordExporterCustomizer {
81-
OtlpHttpLogRecordExporter
82-
.builder()
83-
.setEndpoint(logsEndpoints.getUrl())
84-
.setHeaders(logsEndpoints::getHeaders)
85-
.setCompression(logsEndpoints.getCompression().getUpstreamName())
86-
.apply {
87-
logsEndpoints.getSslContext()?.let {
88-
setSslContext(it.sslContext, it.sslX509TrustManager)
89-
}
90-
}.build()
91-
}.addMetricExporterCustomizer {
92-
OtlpHttpMetricExporter
93-
.builder()
94-
.setEndpoint(metricsEndpoint.getUrl())
95-
.setHeaders(metricsEndpoint::getHeaders)
96-
.setCompression(metricsEndpoint.getCompression().getUpstreamName())
97-
.apply {
98-
metricsEndpoint.getSslContext()?.let {
99-
setSslContext(it.sslContext, it.sslX509TrustManager)
100-
}
101-
}.build()
102-
}.build()
70+
.addSpanExporterCustomizer { createSpanExporter(spansEndpoint) }
71+
.addLogRecordExporterCustomizer { createLogExporter(logsEndpoints) }
72+
.addMetricExporterCustomizer { createMetricExporter(metricsEndpoint) }
73+
.build()
10374
}
10475

76+
private fun createSpanExporter(endpoint: HttpEndpointConnectivity): OtlpHttpSpanExporter =
77+
OtlpHttpSpanExporter
78+
.builder()
79+
.setEndpoint(endpoint.getUrl())
80+
.setHeaders(endpoint::getHeaders)
81+
.setCompression(endpoint.getCompression().getUpstreamName())
82+
.apply {
83+
endpoint.getClientTls()?.let {
84+
setClientTls(it.privateKeyPem, it.certificatePem)
85+
}
86+
endpoint.getSslContext()?.let {
87+
setSslContext(it.sslContext, it.sslX509TrustManager)
88+
}
89+
}.build()
90+
91+
private fun createLogExporter(endpoint: HttpEndpointConnectivity): OtlpHttpLogRecordExporter =
92+
OtlpHttpLogRecordExporter
93+
.builder()
94+
.setEndpoint(endpoint.getUrl())
95+
.setHeaders(endpoint::getHeaders)
96+
.setCompression(endpoint.getCompression().getUpstreamName())
97+
.apply {
98+
endpoint.getClientTls()?.let {
99+
setClientTls(it.privateKeyPem, it.certificatePem)
100+
}
101+
endpoint.getSslContext()?.let {
102+
setSslContext(it.sslContext, it.sslX509TrustManager)
103+
}
104+
}.build()
105+
106+
private fun createMetricExporter(endpoint: HttpEndpointConnectivity): OtlpHttpMetricExporter =
107+
OtlpHttpMetricExporter
108+
.builder()
109+
.setEndpoint(endpoint.getUrl())
110+
.setHeaders(endpoint::getHeaders)
111+
.setCompression(endpoint.getCompression().getUpstreamName())
112+
.apply {
113+
endpoint.getClientTls()?.let {
114+
setClientTls(it.privateKeyPem, it.certificatePem)
115+
}
116+
endpoint.getSslContext()?.let {
117+
setSslContext(it.sslContext, it.sslX509TrustManager)
118+
}
119+
}.build()
120+
105121
private fun Compression.getUpstreamName(): String =
106122
when (this) {
107123
Compression.GZIP -> "gzip"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package io.opentelemetry.android.agent.connectivity
2+
3+
import io.opentelemetry.android.Incubating
4+
5+
/**
6+
* The client key and the certificate chain to use for verifying client when TLS is enabled.
7+
*
8+
* @param privateKeyPem client key PKCS8 in PEM format.
9+
* @param certificatePem client certificate chain in PEM format.
10+
*/
11+
12+
@Incubating
13+
class ClientTlsConnectivity(
14+
val privateKeyPem: ByteArray,
15+
val certificatePem: ByteArray,
16+
)

android-agent/src/main/kotlin/io/opentelemetry/android/agent/connectivity/EndpointConnectivity.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,6 @@ internal interface EndpointConnectivity {
1313
fun getCompression(): Compression
1414

1515
fun getSslContext(): SSLContextConnectivity?
16+
17+
fun getClientTls(): ClientTlsConnectivity?
1618
}

android-agent/src/main/kotlin/io/opentelemetry/android/agent/connectivity/HttpEndpointConnectivity.kt

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,50 @@ internal class HttpEndpointConnectivity private constructor(
1010
private val headers: Map<String, String>,
1111
private val compression: Compression,
1212
private val sslContext: SSLContextConnectivity?,
13+
private val clientTls: ClientTlsConnectivity? = null
1314
) : EndpointConnectivity {
1415
companion object {
1516
fun forTraces(
1617
baseUrl: String,
1718
headers: Map<String, String>,
1819
compression: Compression,
1920
sslContext: SSLContextConnectivity?,
20-
): HttpEndpointConnectivity = HttpEndpointConnectivity(baseUrl.trimEnd('/') + "/v1/traces", headers, compression, sslContext)
21+
clientTls: ClientTlsConnectivity?
22+
): HttpEndpointConnectivity = HttpEndpointConnectivity(
23+
baseUrl.trimEnd('/') + "/v1/traces",
24+
headers,
25+
compression,
26+
sslContext,
27+
clientTls
28+
)
2129

2230
fun forLogs(
2331
baseUrl: String,
2432
headers: Map<String, String>,
2533
compression: Compression,
2634
sslContext: SSLContextConnectivity?,
27-
): HttpEndpointConnectivity = HttpEndpointConnectivity(baseUrl.trimEnd('/') + "/v1/logs", headers, compression, sslContext)
35+
clientTls: ClientTlsConnectivity?
36+
): HttpEndpointConnectivity = HttpEndpointConnectivity(
37+
baseUrl.trimEnd('/') + "/v1/logs",
38+
headers,
39+
compression,
40+
sslContext,
41+
clientTls
42+
)
2843

2944
fun forMetrics(
3045
baseUrl: String,
3146
headers: Map<String, String>,
3247
compression: Compression,
3348
sslContext: SSLContextConnectivity?,
34-
): HttpEndpointConnectivity = HttpEndpointConnectivity(baseUrl.trimEnd('/') + "/v1/metrics", headers, compression, sslContext)
49+
clientTls: ClientTlsConnectivity?
50+
): HttpEndpointConnectivity = HttpEndpointConnectivity(
51+
baseUrl.trimEnd('/') + "/v1/metrics",
52+
headers,
53+
compression,
54+
sslContext,
55+
clientTls
56+
)
3557
}
3658

3759
override fun getUrl(): String = url
@@ -41,4 +63,6 @@ internal class HttpEndpointConnectivity private constructor(
4163
override fun getCompression(): Compression = compression
4264

4365
override fun getSslContext(): SSLContextConnectivity? = sslContext
66+
67+
override fun getClientTls(): ClientTlsConnectivity? = clientTls
4468
}

android-agent/src/main/kotlin/io/opentelemetry/android/agent/dsl/HttpExportConfiguration.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
package io.opentelemetry.android.agent.dsl
77

8+
import io.opentelemetry.android.Incubating
9+
import io.opentelemetry.android.agent.connectivity.ClientTlsConnectivity
810
import io.opentelemetry.android.agent.connectivity.Compression
911
import io.opentelemetry.android.agent.connectivity.HttpEndpointConnectivity
1012
import io.opentelemetry.android.agent.connectivity.SSLContextConnectivity
@@ -34,6 +36,13 @@ class HttpExportConfiguration internal constructor() {
3436
*/
3537
var sslContext: SSLContextConnectivity? = null
3638

39+
/**
40+
* Sets ths client key and the certificate chain to use for verifying client
41+
* for all requests when TLS is enabled.
42+
*/
43+
@Incubating
44+
var clientTls: ClientTlsConnectivity? = null
45+
3746
private val spansConfig: EndpointConfiguration = EndpointConfiguration("")
3847
private val logsConfig: EndpointConfiguration = EndpointConfiguration("")
3948
private val metricsConfig: EndpointConfiguration = EndpointConfiguration("")
@@ -44,6 +53,7 @@ class HttpExportConfiguration internal constructor() {
4453
spansConfig.headers + baseHeaders,
4554
chooseCompression(spansConfig.compression),
4655
sslContext,
56+
clientTls
4757
)
4858

4959
internal fun logsEndpoint(): HttpEndpointConnectivity =
@@ -52,6 +62,7 @@ class HttpExportConfiguration internal constructor() {
5262
logsConfig.headers + baseHeaders,
5363
chooseCompression(logsConfig.compression),
5464
sslContext,
65+
clientTls
5566
)
5667

5768
internal fun metricsEndpoint(): HttpEndpointConnectivity =
@@ -60,6 +71,7 @@ class HttpExportConfiguration internal constructor() {
6071
metricsConfig.headers + baseHeaders,
6172
chooseCompression(metricsConfig.compression),
6273
sslContext,
74+
clientTls
6375
)
6476

6577
private fun chooseUrlSource(cfg: EndpointConfiguration): String = cfg.url.ifBlank { baseUrl }

android-agent/src/test/kotlin/io/opentelemetry/android/agent/connectivity/HttpEndpointConnectivityTest.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,28 @@ class HttpEndpointConnectivityTest {
1515
val headers = mapOf("Authorization" to "Basic something")
1616
val compression = Compression.NONE
1717
val sslContext = SSLContextConnectivity(mockk(), mockk())
18+
val clientTls: ClientTlsConnectivity = mockk()
1819
val tracesConnectivity =
19-
HttpEndpointConnectivity.forTraces("http://some.endpoint", headers, compression, sslContext)
20+
HttpEndpointConnectivity.forTraces("http://some.endpoint", headers, compression, sslContext, clientTls)
2021
val logsConnectivity =
21-
HttpEndpointConnectivity.forLogs("http://some.endpoint/", headers, compression, sslContext)
22+
HttpEndpointConnectivity.forLogs("http://some.endpoint/", headers, compression, sslContext, clientTls)
2223
val metricsConnectivity =
23-
HttpEndpointConnectivity.forMetrics("http://some.endpoint", headers, compression, sslContext)
24+
HttpEndpointConnectivity.forMetrics("http://some.endpoint", headers, compression, sslContext, clientTls)
2425

2526
assertThat(tracesConnectivity.getUrl()).isEqualTo("http://some.endpoint/v1/traces")
2627
assertThat(tracesConnectivity.getHeaders()).isEqualTo(headers)
2728
assertThat(tracesConnectivity.getCompression()).isEqualTo(Compression.NONE)
2829
assertThat(tracesConnectivity.getSslContext()).isEqualTo(sslContext)
30+
assertThat(tracesConnectivity.getClientTls()).isEqualTo(clientTls)
2931
assertThat(logsConnectivity.getUrl()).isEqualTo("http://some.endpoint/v1/logs")
3032
assertThat(logsConnectivity.getHeaders()).isEqualTo(headers)
3133
assertThat(logsConnectivity.getCompression()).isEqualTo(Compression.NONE)
3234
assertThat(logsConnectivity.getSslContext()).isEqualTo(sslContext)
35+
assertThat(logsConnectivity.getClientTls()).isEqualTo(clientTls)
3336
assertThat(metricsConnectivity.getUrl()).isEqualTo("http://some.endpoint/v1/metrics")
3437
assertThat(metricsConnectivity.getHeaders()).isEqualTo(headers)
3538
assertThat(metricsConnectivity.getCompression()).isEqualTo(Compression.NONE)
3639
assertThat(metricsConnectivity.getSslContext()).isEqualTo(sslContext)
40+
assertThat(metricsConnectivity.getClientTls()).isEqualTo(clientTls)
3741
}
3842
}

0 commit comments

Comments
 (0)