Add SSL service connection support for Kafka
See gh-41137
This commit is contained in:
@@ -18,6 +18,7 @@ configurations.all {
|
||||
dependencies {
|
||||
dockerTestImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test"))
|
||||
dockerTestImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support-docker"))
|
||||
dockerTestImplementation(project(":spring-boot-project:spring-boot-testcontainers"))
|
||||
dockerTestImplementation("org.awaitility:awaitility")
|
||||
dockerTestImplementation("org.testcontainers:junit-jupiter")
|
||||
dockerTestImplementation("org.testcontainers:kafka")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
* Copyright 2012-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,16 +23,16 @@ import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import org.testcontainers.kafka.ConfluentKafkaContainer;
|
||||
import org.testcontainers.utility.MountableFile;
|
||||
import smoketest.kafka.Consumer;
|
||||
import smoketest.kafka.Producer;
|
||||
import smoketest.kafka.SampleMessage;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.testcontainers.service.connection.JksKeyStore;
|
||||
import org.springframework.boot.testcontainers.service.connection.JksTrustStore;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.test.context.DynamicPropertyRegistry;
|
||||
import org.springframework.test.context.DynamicPropertySource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
@@ -45,38 +45,14 @@ import static org.hamcrest.Matchers.not;
|
||||
* @author Eddú Meléndez
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
@SpringBootTest(classes = { SampleKafkaSslApplication.class, Producer.class, Consumer.class },
|
||||
properties = { "spring.kafka.security.protocol=SSL",
|
||||
"spring.kafka.properties.ssl.endpoint.identification.algorithm=", "spring.kafka.ssl.bundle=client",
|
||||
"spring.ssl.bundle.jks.client.keystore.location=classpath:ssl/test-client.p12",
|
||||
"spring.ssl.bundle.jks.client.keystore.password=password",
|
||||
"spring.ssl.bundle.jks.client.truststore.location=classpath:ssl/test-ca.p12",
|
||||
"spring.ssl.bundle.jks.client.truststore.password=password" })
|
||||
@SpringBootTest(classes = { SampleKafkaSslApplication.class, Producer.class, Consumer.class })
|
||||
class SampleKafkaSslApplicationTests {
|
||||
|
||||
@Container
|
||||
public static ConfluentKafkaContainer kafka = TestImage.container(ConfluentKafkaContainer.class)
|
||||
.withEnv("KAFKA_LISTENER_SECURITY_PROTOCOL_MAP", "PLAINTEXT:SSL,BROKER:PLAINTEXT,CONTROLLER:PLAINTEXT")
|
||||
.withEnv("KAFKA_AUTO_CREATE_TOPICS_ENABLE", "true")
|
||||
.withEnv("KAFKA_SSL_CLIENT_AUTH", "required")
|
||||
.withEnv("KAFKA_SSL_KEYSTORE_LOCATION", "/etc/kafka/secrets/certs/test-server.p12")
|
||||
.withEnv("KAFKA_SSL_KEYSTORE_PASSWORD", "password")
|
||||
.withEnv("KAFKA_SSL_KEY_PASSWORD", "password")
|
||||
.withEnv("KAFKA_SSL_TRUSTSTORE_LOCATION", "/etc/kafka/secrets/certs/test-ca.p12")
|
||||
.withEnv("KAFKA_SSL_TRUSTSTORE_PASSWORD", "password")
|
||||
.withEnv("KAFKA_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM", "")
|
||||
.withCopyFileToContainer(MountableFile.forClasspathResource("ssl/test-server.p12"),
|
||||
"/etc/kafka/secrets/certs/test-server.p12")
|
||||
.withCopyFileToContainer(MountableFile.forClasspathResource("ssl/credentials"),
|
||||
"/etc/kafka/secrets/certs/credentials")
|
||||
.withCopyFileToContainer(MountableFile.forClasspathResource("ssl/test-ca.p12"),
|
||||
"/etc/kafka/secrets/certs/test-ca.p12");
|
||||
|
||||
@DynamicPropertySource
|
||||
static void kafkaProperties(DynamicPropertyRegistry registry) {
|
||||
registry.add("spring.kafka.bootstrap-servers",
|
||||
() -> String.format("%s:%s", kafka.getHost(), kafka.getMappedPort(9092)));
|
||||
}
|
||||
@ServiceConnection
|
||||
@JksTrustStore(location = "classpath:ssl/test-ca.p12", password = "password")
|
||||
@JksKeyStore(location = "classpath:ssl/test-client.p12", password = "password")
|
||||
public static ConfluentKafkaContainer kafka = TestImage.container(SecureKafkaContainer.class);
|
||||
|
||||
@Autowired
|
||||
private Producer producer;
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2012-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package smoketest.kafka.ssl;
|
||||
|
||||
import org.testcontainers.kafka.ConfluentKafkaContainer;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
import org.testcontainers.utility.MountableFile;
|
||||
|
||||
/**
|
||||
* Kafka container with SSL enabled.
|
||||
*
|
||||
* @author Scott Frederick
|
||||
* @author Eddú Meléndez
|
||||
* @author Moritz Halbritter
|
||||
*/
|
||||
class SecureKafkaContainer extends ConfluentKafkaContainer {
|
||||
|
||||
SecureKafkaContainer(DockerImageName dockerImageName) {
|
||||
super(dockerImageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
withEnv("KAFKA_LISTENER_SECURITY_PROTOCOL_MAP", "PLAINTEXT:SSL,BROKER:PLAINTEXT,CONTROLLER:PLAINTEXT")
|
||||
.withEnv("KAFKA_AUTO_CREATE_TOPICS_ENABLE", "true")
|
||||
.withEnv("KAFKA_SSL_CLIENT_AUTH", "required")
|
||||
.withEnv("KAFKA_SSL_KEYSTORE_LOCATION", "/etc/kafka/secrets/certs/test-server.p12")
|
||||
.withEnv("KAFKA_SSL_KEYSTORE_PASSWORD", "password")
|
||||
.withEnv("KAFKA_SSL_KEY_PASSWORD", "password")
|
||||
.withEnv("KAFKA_SSL_TRUSTSTORE_LOCATION", "/etc/kafka/secrets/certs/test-ca.p12")
|
||||
.withEnv("KAFKA_SSL_TRUSTSTORE_PASSWORD", "password")
|
||||
.withEnv("KAFKA_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM", "");
|
||||
withCopyFileToContainer(MountableFile.forClasspathResource("ssl/test-server.p12"),
|
||||
"/etc/kafka/secrets/certs/test-server.p12");
|
||||
withCopyFileToContainer(MountableFile.forClasspathResource("ssl/credentials"),
|
||||
"/etc/kafka/secrets/certs/credentials");
|
||||
withCopyFileToContainer(MountableFile.forClasspathResource("ssl/test-ca.p12"),
|
||||
"/etc/kafka/secrets/certs/test-ca.p12");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user