Skip to content

Commit da45c59

Browse files
authored
Improved elastic search captured certificate (#191)
1 parent c17ba77 commit da45c59

File tree

8 files changed

+107
-32
lines changed

8 files changed

+107
-32
lines changed

gradle/libs.versions.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ couchbase-client = { module = "com.couchbase.client:java-client", version.ref =
5050
couchbase-client-metrics = { module = "com.couchbase.client:metrics-micrometer", version.ref = "couchbase-client-metrics" }
5151
jackson-kotlin = { module = "com.fasterxml.jackson.module:jackson-module-kotlin", version.ref = "jackson" }
5252
jackson-databind = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson" }
53+
jackson-arrow = { module = "io.arrow-kt:arrow-integrations-jackson-module", version = "0.14.1" }
5354
slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
5455
slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" }
5556
ktor-server-host-common = { module = "io.ktor:ktor-server-host-common", version.ref = "ktor" }

lib/stove-testing-e2e-elasticsearch/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ dependencies {
44
api(libs.elastic)
55
implementation(testLibs.testcontainers.elasticsearch)
66
implementation(libs.jackson.databind)
7+
implementation(libs.jackson.arrow)
78
}
89

910
dependencies {

lib/stove-testing-e2e-elasticsearch/src/main/kotlin/com/trendyol/stove/testing/e2e/elasticsearch/ElasticsearchSystem.kt

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.trendyol.stove.testing.e2e.elasticsearch
22

3-
import arrow.core.getOrElse
4-
import arrow.core.toOption
3+
import arrow.core.*
54
import co.elastic.clients.elasticsearch.ElasticsearchClient
65
import co.elastic.clients.elasticsearch._types.Refresh
76
import co.elastic.clients.elasticsearch._types.query_dsl.Query
@@ -11,8 +10,6 @@ import co.elastic.clients.json.jackson.JacksonJsonpMapper
1110
import co.elastic.clients.transport.rest_client.RestClientTransport
1211
import com.trendyol.stove.functional.Try
1312
import com.trendyol.stove.functional.recover
14-
import com.trendyol.stove.testing.e2e.containers.ExposedCertificate
15-
import com.trendyol.stove.testing.e2e.containers.NoCertificate
1613
import com.trendyol.stove.testing.e2e.system.TestSystem
1714
import com.trendyol.stove.testing.e2e.system.abstractions.*
1815
import kotlinx.coroutines.Dispatchers
@@ -53,13 +50,13 @@ class ElasticsearchSystem internal constructor(
5350
}
5451
}
5552

56-
private fun determineCertificate(): ExposedCertificate = when (context.options.containerOptions.disableSecurity) {
57-
true -> NoCertificate
58-
false -> ElasticsearchExposedCertificate(
59-
context.container.caCertAsBytes().getOrElse { ByteArray(0) },
60-
context.container.createSslContextFromCa()
61-
)
62-
}
53+
private fun determineCertificate(): Option<ElasticsearchExposedCertificate> =
54+
when (context.options.containerOptions.disableSecurity) {
55+
true -> None
56+
false -> ElasticsearchExposedCertificate(
57+
context.container.caCertAsBytes().getOrElse { ByteArray(0) }
58+
).apply { sslContext = context.container.createSslContextFromCa() }.some()
59+
}
6360

6461
override suspend fun afterRun() {
6562
esClient = createEsClient(exposedConfiguration)

lib/stove-testing-e2e-elasticsearch/src/main/kotlin/com/trendyol/stove/testing/e2e/elasticsearch/Extensions.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.trendyol.stove.testing.e2e.elasticsearch
22

33
import arrow.core.getOrElse
4+
import arrow.integrations.jackson.module.registerArrowModule
45
import com.trendyol.stove.testing.e2e.containers.withProvidedRegistry
56
import com.trendyol.stove.testing.e2e.system.TestSystem
67
import com.trendyol.stove.testing.e2e.system.ValidationDsl
@@ -21,6 +22,8 @@ fun TestSystem.withElasticsearch(
2122
register<DefaultIndexMigrator> { options.defaultIndex.migrator }
2223
}
2324

25+
options.objectMapper.registerArrowModule()
26+
2427
return withProvidedRegistry(
2528
imageName = "elasticsearch/elasticsearch:${options.containerOptions.imageVersion}",
2629
registry = options.containerOptions.registry,

lib/stove-testing-e2e-elasticsearch/src/main/kotlin/com/trendyol/stove/testing/e2e/elasticsearch/Options.kt

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ import arrow.core.None
44
import arrow.core.Option
55
import arrow.core.none
66
import co.elastic.clients.elasticsearch.ElasticsearchClient
7+
import com.fasterxml.jackson.annotation.JsonCreator
8+
import com.fasterxml.jackson.annotation.JsonIgnore
9+
import com.fasterxml.jackson.annotation.JsonProperty
710
import com.fasterxml.jackson.databind.ObjectMapper
8-
import com.trendyol.stove.testing.e2e.containers.ExposedCertificate
11+
import com.trendyol.stove.functional.Reflect
912
import com.trendyol.stove.testing.e2e.database.migrations.DatabaseMigration
1013
import com.trendyol.stove.testing.e2e.database.migrations.MigrationCollection
1114
import com.trendyol.stove.testing.e2e.serialization.StoveObjectMapper
@@ -16,6 +19,7 @@ import org.apache.http.client.config.RequestConfig
1619
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder
1720
import org.elasticsearch.client.RestClient
1821
import org.testcontainers.elasticsearch.ElasticsearchContainer
22+
import java.util.*
1923
import javax.net.ssl.SSLContext
2024
import kotlin.time.Duration.Companion.minutes
2125

@@ -34,23 +38,63 @@ data class ElasticsearchSystemOptions(
3438
* @see MigrationCollection
3539
* @see DatabaseMigration
3640
*/
37-
fun migrations(migration: MigrationCollection<ElasticsearchClient>.() -> Unit): ElasticsearchSystemOptions = migration(
38-
migrationCollection
39-
).let {
40-
this
41-
}
41+
fun migrations(migration: MigrationCollection<ElasticsearchClient>.() -> Unit): ElasticsearchSystemOptions =
42+
migration(
43+
migrationCollection
44+
).let {
45+
this
46+
}
4247
}
4348

4449
data class ElasticsearchExposedCertificate(
45-
val bytes: ByteArray,
46-
val sslContext: SSLContext
47-
) : ExposedCertificate
50+
val bytes: ByteArray
51+
) {
52+
53+
@get:JsonIgnore
54+
@set:JsonIgnore
55+
var sslContext: SSLContext = SSLContext.getDefault()
56+
internal set
57+
58+
override fun equals(other: Any?): Boolean {
59+
if (this === other) return true
60+
if (javaClass != other?.javaClass) return false
61+
62+
other as ElasticsearchExposedCertificate
63+
64+
if (!bytes.contentEquals(other.bytes)) return false
65+
if (sslContext != other.sslContext) return false
66+
67+
return true
68+
}
69+
70+
override fun hashCode(): Int {
71+
var result = bytes.contentHashCode()
72+
result = 31 * result + sslContext.hashCode()
73+
return result
74+
}
75+
76+
companion object {
77+
@JsonCreator
78+
@JvmStatic
79+
fun create(
80+
@JsonProperty bytes: ByteArray
81+
): ElasticsearchExposedCertificate {
82+
val container = ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:latest")
83+
Reflect(container) {
84+
on<Optional<ByteArray>>("caCertAsBytes").then(Optional.of(bytes))
85+
}
86+
return ElasticsearchExposedCertificate(bytes).apply {
87+
sslContext = container.createSslContextFromCa()
88+
}
89+
}
90+
}
91+
}
4892

4993
data class ElasticSearchExposedConfiguration(
5094
val host: String,
5195
val port: Int,
5296
val password: String,
53-
val certificate: ExposedCertificate
97+
val certificate: Option<ElasticsearchExposedCertificate>
5498
) : ExposedConfiguration
5599

56100
data class ElasticsearchContext(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.trendyol.stove.testing.e2e.elasticsearch
2+
3+
import arrow.integrations.jackson.module.registerArrowModule
4+
import com.fasterxml.jackson.module.kotlin.readValue
5+
import com.trendyol.stove.functional.get
6+
import com.trendyol.stove.testing.e2e.serialization.StoveObjectMapper
7+
import com.trendyol.stove.testing.e2e.system.abstractions.StateWithProcess
8+
import io.kotest.core.spec.style.FunSpec
9+
import io.kotest.matchers.ints.shouldBeGreaterThan
10+
import io.kotest.matchers.shouldBe
11+
import io.kotest.matchers.shouldNotBe
12+
13+
class ElasticsearchExposedCertificateTest : FunSpec({
14+
test("ser/de") {
15+
val state = """
16+
{
17+
"state": {
18+
"host": "localhost",
19+
"port": 50543,
20+
"password": "password",
21+
"certificate": {
22+
"bytes": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZXakNDQTBLZ0F3SUJBZ0lWQU4wclloSXpaMS90Rmg5NmR3WGI1b1lWWnl4UU1BMEdDU3FHU0liM0RRRUIKQ3dVQU1Ed3hPakE0QmdOVkJBTVRNVVZzWVhOMGFXTnpaV0Z5WTJnZ2MyVmpkWEpwZEhrZ1lYVjBieTFqYjI1bQphV2QxY21GMGFXOXVJRWhVVkZBZ1EwRXdIaGNOTWpNd09ERTFNVGd5TWpJNFdoY05Nall3T0RFME1UZ3lNakk0CldqQThNVG93T0FZRFZRUURFekZGYkdGemRHbGpjMlZoY21Ob0lITmxZM1Z5YVhSNUlHRjFkRzh0WTI5dVptbG4KZFhKaGRHbHZiaUJJVkZSUUlFTkJNSUlDSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQWc4QU1JSUNDZ0tDQWdFQQppcDVGaWwySUMyRGhYbHkyV3RYTFliTnJUbHNkQklZQ3JvK0N1QU40djJHM3RuMkNQTmVoMnM2V0ovRUNrRitVCndJUVVKWEN0Mm43aEJDWkY4M1BlQ1JabWZyWkE0VXNtdzBYWS9OWWpTcnJRQXVtODYvamFZM0lMVGYzU1Jnei8KaWNFVEJCRVM1eTdmSFZlU0xmTjl1ME9hSC9tTnN5Q3FoMERMRFZrWXR5MHNJZXorb1paNmtxN2UrRE1OeHB5Sgp1cjRvUGJ5ekdmY1dnZDdnMll5T2RxNEd1TmFOck8ySjFVZG5BV3B5TVdnME5TSzd1TGlEZ0w5a25ZZlBnMmhQCisrWVpnVkJNNXJBMXJhY2x3c0U0NWJNVlErKzRyWEhhbDUwdS83VmN6a3M5QTREVDc3ZHVyOC9aM1hONWtpMm0KaWNTemJDTHlLdTZwdUhLQWhCdFMyWnlMMXBYN09RSVA2aWZLaVpaU1ZYUGZnMGk5cjVQL3ZFZTJoVXpTTDRVLwpsSWQvaWJUQWtIcmZGbEErN2FreFNzcFJoalMra1ZTQndyR05KQ3BDbWsraitxSnB5Sis5aTNWb0pkanVvemprClk2bS9EZG9kc21LdUZFYUdZNytBT1RVMjAwN0ZjZWdXUEJWejgzU051WmpwbURCczMzS25oeG5WM0RBb0QzUm4KbkNoV2ZQTGo4TUl1OG9tMll3RUpZMUtLR1hzUzU5TWtyclpuQnNjdzl0S0prMFQyRHlLM2dWckY5UnJpMk1mTwpKY3FCWUhBSHRQTHRQZU5STHJLUmxtYkh4NXJFMkNCWEJWQWJ1bU1EaGRIbE1lTWtwT1p3WnoyQWljWUV1anhlClU0TUl5LzczU1RHakhtcGpVT3dKcjNMdVdqVlBMNDlZeTZZWmNPbENsTThDQXdFQUFhTlRNRkV3SFFZRFZSME8KQkJZRUZNUTlobHVXN3VzdGQwZkZDNU5zSkNyTDhaTStNQjhHQTFVZEl3UVlNQmFBRk1ROWhsdVc3dXN0ZDBmRgpDNU5zSkNyTDhaTStNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEUVlKS29aSWh2Y05BUUVMQlFBRGdnSUJBSEdOCjQ1Nm1iYXdKUHNLTVgvQlowanB2LytTbCtMTTB6U2gxeEF1YXlmbDk3WnBlbS80QkhGcU5vTUxGOEVqczhXcHoKUHU1Y3Y5VVFaZXNaWVVsNHE4ODY5TW03QnQ5UHVRcUJBR25VbTU3alhMRkRsdDRvVTFvZmVpalF1YkZ3M0wwMwpGa2NsQ3psZ2JhV21vb2ZKRTdKK2FEMGo5bHNOWllKem9tQlN6QnZGTC9uK0ptS0poQVk4SDNwTkNqdExtbXZjClZPbmluQWFScGxLQndSS1RRYm1ZVE53QXVTcEhvSUk4empqK3pGWm54MzVqSitJY0YwblQ1Q3FQT0tCcllxTmwKN21kTnU0OGs0eUpiY0JtYXNoa3BRdkQra2Q1RFJBWmZXZ2tjZzVZUk1RUnE3RnVpWkhxcmFVdWV2WmZ3dnB2UApqMmV5M0QwMG5aSUVIN3I0alVpVnl0SGNGejVQU29zRmIwZDlmWkRJYmJGanRQblpSTEVxbS8wd3N1V25VSVdRCnlSWTNvclNiMUZIYjdYQUlUdHlnZlZQZnlUV0lnemdtbjFCR3Z2eE5sYjIyVnB4TXcvaEpLWTU0WDRjc2s1RzkKbHZMNUVzT3BvYnZvWVJRNU9taHlJT1ZGSHUwcjRKZWkzcGJ3dTczWmlnLzNFanJLY0lRS0ttYzdhQUFkbGREeQpid0dRWDdvYzRLS1lra2JPNFNNQTRTZzUxQjJFZFEzVGYrSHJlUjFTcHN1TlB1U2p0aGY5MGY2eWYrU1d0NU04CnY2RmpVRy9sR0NGTndJTTd2N1o3SHhMVnIvbVg4MTRKVzBGREdLUmhHRHd3SDUzcTJYSmRaaEl5RlNaeWtuc1UKdmJLeW51Vm43czZrU1pYbnh2NnYyTTNsL09ZMjdpNHdUVnB6bzhXbgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=="
23+
}
24+
},
25+
"processId": 10496
26+
}
27+
""".trimIndent()
28+
val j = StoveObjectMapper.byConfiguring { this.registerArrowModule() }
29+
val stateWithProcess = j.readValue<StateWithProcess<ElasticSearchExposedConfiguration>>(state)
30+
val serialize = j.writeValueAsString(stateWithProcess)
31+
val stateWithProcess2 = j.readValue<StateWithProcess<ElasticSearchExposedConfiguration>>(serialize)
32+
33+
val cert = stateWithProcess2.state.certificate.get()
34+
cert.bytes.size shouldBeGreaterThan 0
35+
cert.sslContext shouldNotBe null
36+
cert.sslContext.protocol shouldBe "TLSv1.3"
37+
}
38+
})

lib/stove-testing-e2e/src/main/kotlin/com/trendyol/stove/functional/Reflect.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ class Reflect<T : Any>(val instance: T) {
1818
propertySelector: T.() -> KProperty<R>
1919
): OnGoingReflect<R> = OnGoingReflect(instance, propertySelector(instance).name)
2020

21+
inline fun <reified R> on(property: String): OnGoingReflect<R> = OnGoingReflect(instance, property)
22+
2123
companion object {
2224
inline operator fun <reified T : Any> invoke(
2325
instance: T,

lib/stove-testing-e2e/src/main/kotlin/com/trendyol/stove/testing/e2e/containers/ExposedCertificate.kt

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)