This is an automated email from the ASF dual-hosted git repository.

jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git


The following commit(s) were added to refs/heads/main by this push:
     new 1de918f30a Kafka tests in fips
1de918f30a is described below

commit 1de918f30a6a2f9e784b3face5c2956aa94ee02f
Author: JiriOndrusek <ondrusek.j...@gmail.com>
AuthorDate: Tue May 14 16:08:30 2024 +0200

    Kafka tests in fips
---
 .../{kafka => certificate-generator}/pom.xml       |  20 ++--
 .../TestCertificateGenerationExtension.java        | 127 +++++++++++++++++++++
 .../test/support/certificate/TestCertificates.java |  55 +++++++++
 integration-tests-support/kafka/pom.xml            |   4 +
 .../test/support/kafka/KafkaTestResource.java      |  78 ++++++++++++-
 .../test/support/kafka/KafkaTestSupport.java       |  37 ------
 .../kafka/src/main/resources/log4j.properties      |  23 ++++
 integration-tests-support/pom.xml                  |   1 +
 .../quarkus/test/DisabledIfFipsModeCondition.java  |   2 +-
 .../quarkus/test/EnabledIfFipsModeCondition.java   |  29 +----
 ...dIfFipsModeCondition.java => FipsModeUtil.java} |  40 ++-----
 integration-tests/kafka-sasl-ssl/pom.xml           |   5 +
 .../camel/quarkus/kafka/sasl/KafkaSaslSslTest.java |   7 ++
 .../kafka/sasl/KafkaSaslSslTestResource.java       |  76 ++++--------
 .../test/resources/config/generate-certificates.sh |  39 -------
 .../src/test/resources/config/kafka-keystore.p12   | Bin 2451 -> 0 bytes
 .../src/test/resources/config/kafka-truststore.p12 | Bin 1010 -> 0 bytes
 .../test/resources/config/kafka_server_jaas.conf   |   5 +-
 .../quarkus/kafka/sasl/KafkaSaslBindingTest.java   |   2 +
 integration-tests/kafka-ssl/pom.xml                |   5 +
 .../camel/quarkus/kafka/ssl/KafkaSslTest.java      |  10 ++
 .../quarkus/kafka/ssl/KafkaSslTestResource.java    |  74 +++---------
 .../test/resources/config/generate-certificates.sh |  39 -------
 .../src/test/resources/config/kafka-keystore.p12   | Bin 2451 -> 0 bytes
 .../src/test/resources/config/kafka-truststore.p12 | Bin 1010 -> 0 bytes
 pom.xml                                            |   1 +
 poms/bom-test/pom.xml                              |  10 ++
 27 files changed, 385 insertions(+), 304 deletions(-)

diff --git a/integration-tests-support/kafka/pom.xml 
b/integration-tests-support/certificate-generator/pom.xml
similarity index 86%
copy from integration-tests-support/kafka/pom.xml
copy to integration-tests-support/certificate-generator/pom.xml
index 736a0e369b..0bcbf9f57d 100644
--- a/integration-tests-support/kafka/pom.xml
+++ b/integration-tests-support/certificate-generator/pom.xml
@@ -26,21 +26,25 @@
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
-    <artifactId>camel-quarkus-integration-tests-support-kafka</artifactId>
-    <name>Camel Quarkus :: Integration Tests :: Support :: Kafka</name>
+    
<artifactId>camel-quarkus-integration-tests-support-certificate-generator</artifactId>
+    <name>Camel Quarkus :: Integration Tests :: Support :: Certificate 
generator</name>
 
     <dependencies>
         <dependency>
-            <groupId>io.quarkus</groupId>
-            <artifactId>quarkus-kafka-client</artifactId>
+            <groupId>me.escoffier.certs</groupId>
+            <artifactId>certificate-generator-junit5</artifactId>
         </dependency>
         <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-integration-test-support</artifactId>
         </dependency>
         <dependency>
-            <groupId>io.strimzi</groupId>
-            <artifactId>strimzi-test-container</artifactId>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-junit4-mock</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.testcontainers</groupId>
+            <artifactId>testcontainers</artifactId>
             <exclusions>
                 <exclusion>
                     <groupId>junit</groupId>
@@ -48,10 +52,6 @@
                 </exclusion>
             </exclusions>
         </dependency>
-        <dependency>
-            <groupId>io.quarkus</groupId>
-            <artifactId>quarkus-junit4-mock</artifactId>
-        </dependency>
     </dependencies>
 
     <build>
diff --git 
a/integration-tests-support/certificate-generator/src/main/java/org/apache/camel/quarkus/test/support/certificate/TestCertificateGenerationExtension.java
 
b/integration-tests-support/certificate-generator/src/main/java/org/apache/camel/quarkus/test/support/certificate/TestCertificateGenerationExtension.java
new file mode 100644
index 0000000000..c695fdcaab
--- /dev/null
+++ 
b/integration-tests-support/certificate-generator/src/main/java/org/apache/camel/quarkus/test/support/certificate/TestCertificateGenerationExtension.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *      http://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 org.apache.camel.quarkus.test.support.certificate;
+
+import java.io.File;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+
+import me.escoffier.certs.AliasRequest;
+import me.escoffier.certs.CertificateFiles;
+import me.escoffier.certs.CertificateGenerator;
+import me.escoffier.certs.CertificateRequest;
+import me.escoffier.certs.junit5.Alias;
+import me.escoffier.certs.junit5.Certificate;
+import org.jboss.logging.Logger;
+import org.junit.jupiter.api.extension.*;
+import org.junit.platform.commons.util.AnnotationUtils;
+import org.testcontainers.DockerClientFactory;
+
+/**
+ * Extension is based on
+ * 
https://github.com/cescoffier/certificate-generator/blob/main/certificate-generator-junit5/src/main/java/me/escoffier/certs/junit5/CertificateGenerationExtension.java
+ *
+ * Unfortunately there is no way of extending the original Extension with 
functionality of modifying CN and
+ * SubjectAlternativeName
+ * based on docker host (required for usage with external docker host)
+ * Therefore I created a new annotation 'TestCertificates' which would use 
this new extension.
+ */
+public class TestCertificateGenerationExtension implements BeforeAllCallback, 
ParameterResolver {
+    private static final Logger LOGGER = 
Logger.getLogger(TestCertificateGenerationExtension.class);
+
+    public static TestCertificateGenerationExtension 
getInstance(ExtensionContext extensionContext) {
+        return extensionContext.getStore(ExtensionContext.Namespace.GLOBAL)
+                .get(TestCertificateGenerationExtension.class, 
TestCertificateGenerationExtension.class);
+    }
+
+    List<CertificateFiles> certificateFiles = new ArrayList<>();
+
+    @Override
+    public void beforeAll(ExtensionContext extensionContext) throws Exception {
+
+        extensionContext.getStore(ExtensionContext.Namespace.GLOBAL)
+                
.getOrComputeIfAbsent(TestCertificateGenerationExtension.class, c -> this);
+        var maybe = 
AnnotationUtils.findAnnotation(extensionContext.getRequiredTestClass(), 
TestCertificates.class);
+        if (maybe.isEmpty()) {
+            return;
+        }
+        var annotation = maybe.get();
+
+        //cn and alternativeSubjectName might be different (to reflect docker 
host)
+        Optional<String> cn = resolveDockerHost();
+        Optional<String> altSubName = cn.stream().map(h -> 
"IP:%s".formatted(h)).findAny();
+
+        for (Certificate certificate : annotation.certificates()) {
+            String baseDir = annotation.baseDir();
+            File file = new File(baseDir);
+            file.mkdirs();
+            CertificateGenerator generator = new 
CertificateGenerator(file.toPath(), annotation.replaceIfExists());
+
+            CertificateRequest request = new CertificateRequest()
+                    .withName(certificate.name())
+                    .withClientCertificate(certificate.client())
+                    .withFormats(Arrays.asList(certificate.formats()))
+                    .withCN(cn.orElse(certificate.cn()))
+                    .withPassword(certificate.password().isEmpty() ? null : 
certificate.password())
+                    .withDuration(Duration.ofDays(certificate.duration()));
+
+            if (altSubName.isPresent()) {
+                request.withSubjectAlternativeName(altSubName.get());
+            }
+
+            for (String san : certificate.subjectAlternativeNames()) {
+                request.withSubjectAlternativeName(san);
+            }
+
+            for (Alias alias : certificate.aliases()) {
+                AliasRequest nested = new AliasRequest()
+                        .withCN(alias.cn())
+                        .withPassword(alias.password())
+                        .withClientCertificate(alias.client());
+                request.withAlias(alias.name(), nested);
+                for (String s : alias.subjectAlternativeNames()) {
+                    nested.withSubjectAlternativeName(s);
+                }
+            }
+
+            certificateFiles.addAll(generator.generate(request));
+        }
+    }
+
+    private Optional<String> resolveDockerHost() {
+        String dockerHost = 
DockerClientFactory.instance().dockerHostIpAddress();
+        if (!dockerHost.equals("localhost") && 
!dockerHost.equals("127.0.0.1")) {
+            return Optional.of(dockerHost);
+        }
+        return Optional.empty();
+    }
+
+    @Override
+    public boolean supportsParameter(ParameterContext parameterContext, 
ExtensionContext extensionContext)
+            throws ParameterResolutionException {
+        throw new IllegalArgumentException("Not supported!");
+    }
+
+    @Override
+    public Object resolveParameter(ParameterContext parameterContext, 
ExtensionContext extensionContext)
+            throws ParameterResolutionException {
+        throw new IllegalArgumentException("Not supported!");
+    }
+}
diff --git 
a/integration-tests-support/certificate-generator/src/main/java/org/apache/camel/quarkus/test/support/certificate/TestCertificates.java
 
b/integration-tests-support/certificate-generator/src/main/java/org/apache/camel/quarkus/test/support/certificate/TestCertificates.java
new file mode 100644
index 0000000000..0d686dbc58
--- /dev/null
+++ 
b/integration-tests-support/certificate-generator/src/main/java/org/apache/camel/quarkus/test/support/certificate/TestCertificates.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *      http://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 org.apache.camel.quarkus.test.support.certificate;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import me.escoffier.certs.junit5.Certificate;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+/**
+ * Based on
+ * 
https://github.com/cescoffier/certificate-generator/blob/main/certificate-generator-junit5/src/main/java/me/escoffier/certs/junit5/Certificates.java
+ * Generates certificates before the tests via 
'TestCertificateGenerationExtension' so the new certificates
+ * are customized to fullfill a remote docker host (if required).
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@ExtendWith(TestCertificateGenerationExtension.class)
+@Inherited
+public @interface TestCertificates {
+
+    /**
+     * The base directory in which certificates will be generated.
+     */
+    String baseDir();
+
+    /**
+     * The certificates to generate.
+     * Must not be empty.
+     */
+    Certificate[] certificates();
+
+    /**
+     * Whether to replace the certificates if they already exist.
+     */
+    boolean replaceIfExists() default false;
+}
diff --git a/integration-tests-support/kafka/pom.xml 
b/integration-tests-support/kafka/pom.xml
index 736a0e369b..2cc5a91e13 100644
--- a/integration-tests-support/kafka/pom.xml
+++ b/integration-tests-support/kafka/pom.xml
@@ -52,6 +52,10 @@
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-junit4-mock</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-integration-test-support</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
diff --git 
a/integration-tests-support/kafka/src/main/java/org/apache/camel/quarkus/test/support/kafka/KafkaTestResource.java
 
b/integration-tests-support/kafka/src/main/java/org/apache/camel/quarkus/test/support/kafka/KafkaTestResource.java
index 5e3fd138fa..a38e7c1f74 100644
--- 
a/integration-tests-support/kafka/src/main/java/org/apache/camel/quarkus/test/support/kafka/KafkaTestResource.java
+++ 
b/integration-tests-support/kafka/src/main/java/org/apache/camel/quarkus/test/support/kafka/KafkaTestResource.java
@@ -18,12 +18,18 @@ package org.apache.camel.quarkus.test.support.kafka;
 
 import java.util.Collections;
 import java.util.Map;
+import java.util.function.Function;
 
+import com.github.dockerjava.api.exception.NotFoundException;
 import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
 import io.strimzi.test.container.StrimziKafkaContainer;
+import org.apache.camel.quarkus.test.FipsModeUtil;
 import org.eclipse.microprofile.config.ConfigProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.testcontainers.containers.ContainerFetchException;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.images.builder.ImageFromDockerfile;
 import org.testcontainers.utility.TestcontainersConfiguration;
 
 public class KafkaTestResource implements QuarkusTestResourceLifecycleManager {
@@ -31,18 +37,14 @@ public class KafkaTestResource implements 
QuarkusTestResourceLifecycleManager {
     private static final Logger LOGGER = 
LoggerFactory.getLogger(KafkaTestResource.class);
 
     private StrimziKafkaContainer container;
+    private GenericContainer j17container;
 
     @Override
     public Map<String, String> start() {
         LOGGER.info(TestcontainersConfiguration.getInstance().toString());
 
         try {
-            container = new StrimziKafkaContainer(KAFKA_IMAGE_NAME)
-                    /* Added container startup logging because of 
https://github.com/apache/camel-quarkus/issues/2461 */
-                    .withLogConsumer(frame -> 
System.out.print(frame.getUtf8String()))
-                    .waitForRunning();
-
-            container.start();
+            startContainer(KAFKA_IMAGE_NAME, name -> new 
StrimziKafkaContainer(name));
 
             return Collections.singletonMap("camel.component.kafka.brokers", 
container.getBootstrapServers());
         } catch (Exception e) {
@@ -50,6 +52,62 @@ public class KafkaTestResource implements 
QuarkusTestResourceLifecycleManager {
         }
     }
 
+    public String start(Function<String, StrimziKafkaContainer> 
containerSupplier) {
+        LOGGER.info(TestcontainersConfiguration.getInstance().toString());
+
+        //if FIPS environment is present, custom container using J17 has to 
used because:
+        // Password-based encryption support in FIPs mode was implemented in 
the Red Hat build of OpenJDK 17 update 4
+        if (FipsModeUtil.isFipsMode()) {
+            //custom image should be cached for the next usages with following 
id
+            String customImageName = "camel-quarkus-test-custom-" + 
KAFKA_IMAGE_NAME.replaceAll("[\\./]", "-");
+
+            try {
+                //in case that the image is not accessible, fetch exception is 
thrown
+                startContainer(customImageName, containerSupplier);
+            } catch (ContainerFetchException e) {
+                if (e.getCause() instanceof NotFoundException) {
+                    LOGGER.info("Custom image for kafka (%s) does not exist. 
Has to be created.", customImageName);
+
+                    //start of the customized container will create the image
+                    //it is not possible to customize existing 
StrimziKafkaContainer. Testcontainer API doe not allow
+                    //to customize the image.
+                    // This workaround can be removed once the strimzi 
container with openjdk 17 is released.
+                    // According to 
https://strimzi.io/blog/2023/01/25/running-apache-kafka-on-fips-enabled-kubernetes-cluster/
+                    // image should exist
+                    j17container = new GenericContainer(
+                            new ImageFromDockerfile(customImageName, false)
+                                    .withDockerfileFromBuilder(builder -> 
builder
+                                            
.from("quay.io/strimzi-test-container/test-container:latest-kafka-3.2.1")
+                                            .env("JAVA_HOME", 
"/usr/lib/jvm/jre-17")
+                                            .env("PATH", 
"/usr/lib/jvm/jre-17/bin:$PATH")
+                                            .user("root")
+                                            .run("microdnf install -y --nodocs 
java-17-openjdk-headless glibc-langpack-en && microdnf clean all")));
+                    j17container.start();
+
+                    LOGGER.info("Custom image for kafka (%s) has been 
created.", customImageName);
+
+                    //start kafka container again
+                    startContainer(customImageName, containerSupplier);
+                }
+            }
+        } else {
+            startContainer(KAFKA_IMAGE_NAME, containerSupplier);
+        }
+
+        return container.getBootstrapServers();
+
+    }
+
+    private void startContainer(String imageName, Function<String, 
StrimziKafkaContainer> containerSupplier) {
+        container = containerSupplier.apply(imageName);
+
+        /* Added container startup logging because of 
https://github.com/apache/camel-quarkus/issues/2461 */
+        container.withLogConsumer(frame -> 
System.out.print(frame.getUtf8String()))
+                //                .withEnv("KAFKA_LOG4J_OPTS", 
"-Dlog4j.configuration=file:/log4j.properties")
+                .waitForRunning()
+                .start();
+    }
+
     @Override
     public void stop() {
         if (container != null) {
@@ -59,6 +117,13 @@ public class KafkaTestResource implements 
QuarkusTestResourceLifecycleManager {
                 // ignored
             }
         }
+        if (j17container != null) {
+            try {
+                j17container.stop();
+            } catch (Exception e) {
+                // ignored
+            }
+        }
     }
 
     @Override
@@ -66,4 +131,5 @@ public class KafkaTestResource implements 
QuarkusTestResourceLifecycleManager {
         testInjector.injectIntoFields(container,
                 new TestInjector.AnnotatedAndMatchesType(InjectKafka.class, 
StrimziKafkaContainer.class));
     }
+
 }
diff --git 
a/integration-tests-support/kafka/src/main/java/org/apache/camel/quarkus/test/support/kafka/KafkaTestSupport.java
 
b/integration-tests-support/kafka/src/main/java/org/apache/camel/quarkus/test/support/kafka/KafkaTestSupport.java
index 54170c5216..a62d6d475a 100644
--- 
a/integration-tests-support/kafka/src/main/java/org/apache/camel/quarkus/test/support/kafka/KafkaTestSupport.java
+++ 
b/integration-tests-support/kafka/src/main/java/org/apache/camel/quarkus/test/support/kafka/KafkaTestSupport.java
@@ -16,16 +16,12 @@
  */
 package org.apache.camel.quarkus.test.support.kafka;
 
-import java.nio.file.Path;
 import java.util.Optional;
 import java.util.Properties;
 
 import org.apache.kafka.clients.CommonClientConfigs;
 import org.eclipse.microprofile.config.Config;
 import org.eclipse.microprofile.config.ConfigProvider;
-import org.testcontainers.DockerClientFactory;
-import org.testcontainers.containers.GenericContainer;
-import org.testcontainers.utility.MountableFile;
 
 public final class KafkaTestSupport {
 
@@ -59,37 +55,4 @@ public final class KafkaTestSupport {
     public static void setKafkaConfigFromProperty(Properties props, String 
key, String valueKey) {
         props.put(key, getKafkaConfigValue(valueKey));
     }
-
-    public static void regenerateCertificatesForDockerHost(
-            Path configDir,
-            String certificateScript,
-            String keyStoreFile,
-            String trustStoreFile) {
-        String dockerHost = 
DockerClientFactory.instance().dockerHostIpAddress();
-        if (!dockerHost.equals("localhost") && 
!dockerHost.equals("127.0.0.1")) {
-            // Run certificate generation in a container in case the target 
platform does not have prerequisites like OpenSSL installed (E.g on Windows)
-            String imageName = 
ConfigProvider.getConfig().getValue("eclipse-temurin.container.image", 
String.class);
-            try (GenericContainer<?> container = new 
GenericContainer<>(imageName)) {
-                container.withCreateContainerCmdModifier(modifier -> {
-                    modifier.withEntrypoint("/bin/bash");
-                    modifier.withStdinOpen(true);
-                });
-                container.setWorkingDirectory("/");
-                container.start();
-
-                String host = container.getHost();
-                container.copyFileToContainer(
-                        MountableFile.forClasspathResource("config/" + 
certificateScript),
-                        "/" + certificateScript);
-                container.execInContainer("/bin/bash", "/" + 
certificateScript, host,
-                        "DNS:%s,IP:%s".formatted(host, host));
-                container.copyFileFromContainer("/" + keyStoreFile,
-                        configDir.resolve(keyStoreFile).toString());
-                container.copyFileFromContainer("/" + trustStoreFile,
-                        configDir.resolve(trustStoreFile).toString());
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-        }
-    }
 }
diff --git 
a/integration-tests-support/kafka/src/main/resources/log4j.properties 
b/integration-tests-support/kafka/src/main/resources/log4j.properties
new file mode 100644
index 0000000000..061c5b6877
--- /dev/null
+++ b/integration-tests-support/kafka/src/main/resources/log4j.properties
@@ -0,0 +1,23 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You 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
+##
+##      http://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.
+## ---------------------------------------------------------------------------
+# Set root logger level to DEBUG and its only appender to CONSOLE.
+log4j.rootLogger=TRACE, CONSOLE
+
+# Console appender configuration
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%-5p] 
%c{1}:%L - %m%n
diff --git a/integration-tests-support/pom.xml 
b/integration-tests-support/pom.xml
index 378254700c..d0d48a1886 100644
--- a/integration-tests-support/pom.xml
+++ b/integration-tests-support/pom.xml
@@ -50,6 +50,7 @@
         <module>activemq</module>
         <module>aws2</module>
         <module>azure</module>
+        <module>certificate-generator</module>
         <module>custom-dataformat</module>
         <module>custom-log-component</module>
         <module>custom-routes-collector</module>
diff --git 
a/integration-tests-support/test-support/src/main/java/org/apache/camel/quarkus/test/DisabledIfFipsModeCondition.java
 
b/integration-tests-support/test-support/src/main/java/org/apache/camel/quarkus/test/DisabledIfFipsModeCondition.java
index 984e8bde8a..f452be2c22 100644
--- 
a/integration-tests-support/test-support/src/main/java/org/apache/camel/quarkus/test/DisabledIfFipsModeCondition.java
+++ 
b/integration-tests-support/test-support/src/main/java/org/apache/camel/quarkus/test/DisabledIfFipsModeCondition.java
@@ -39,7 +39,7 @@ public class DisabledIfFipsModeCondition extends 
EnabledIfFipsModeCondition {
 
     private ConditionEvaluationResult map(DisabledIfFipsMode annotation) {
         List<String> providersToMatch = List.of(annotation.providers());
-        Optional<String> fipsProviders = findFipsProvider(providersToMatch);
+        Optional<String> fipsProviders = 
FipsModeUtil.findFipsProvider(providersToMatch);
 
         if (fipsProviders == null) {
             return enabled("No FIPS security providers were detected");
diff --git 
a/integration-tests-support/test-support/src/main/java/org/apache/camel/quarkus/test/EnabledIfFipsModeCondition.java
 
b/integration-tests-support/test-support/src/main/java/org/apache/camel/quarkus/test/EnabledIfFipsModeCondition.java
index f858c2b835..89ca33ec01 100644
--- 
a/integration-tests-support/test-support/src/main/java/org/apache/camel/quarkus/test/EnabledIfFipsModeCondition.java
+++ 
b/integration-tests-support/test-support/src/main/java/org/apache/camel/quarkus/test/EnabledIfFipsModeCondition.java
@@ -16,8 +16,6 @@
  */
 package org.apache.camel.quarkus.test;
 
-import java.security.Provider;
-import java.security.Security;
 import java.util.List;
 import java.util.Optional;
 
@@ -39,7 +37,7 @@ public class EnabledIfFipsModeCondition implements 
ExecutionCondition {
 
     private ConditionEvaluationResult map(EnabledIfFipsMode annotation) {
         List<String> providersToMatch = List.of(annotation.providers());
-        Optional<String> fipsProviders = findFipsProvider(providersToMatch);
+        Optional<String> fipsProviders = 
FipsModeUtil.findFipsProvider(providersToMatch);
 
         if (fipsProviders == null) {
             return disabled("No FIPS security providers were detected");
@@ -51,29 +49,4 @@ public class EnabledIfFipsModeCondition implements 
ExecutionCondition {
         return enabled("Detected FIPS security provider " + 
fipsProviders.get());
     }
 
-    /**
-     * Returns null if system is not in fips mode.
-     * Returns Optional.empty if system is in fips mode and there is some 
provider containing "fips"
-     * Returns Optional.name if system is in fips mode and there is a match 
with the provided providers
-     * (the last 2 options allows to differentiate reason of the 
enablement/disablement)
-     */
-    Optional<String> findFipsProvider(List<String> providersToMatch) {
-        Provider[] jdkProviders = Security.getProviders();
-        int matchCount = 0;
-
-        for (Provider provider : jdkProviders) {
-            if (providersToMatch.isEmpty() && 
provider.getName().toLowerCase().contains("fips")) {
-                return Optional.of(provider.getName());
-            } else if (providersToMatch.contains(provider.getName())) {
-                matchCount++;
-            }
-        }
-
-        if (!providersToMatch.isEmpty() && matchCount == 
providersToMatch.size()) {
-            return Optional.empty();
-        }
-
-        return null;
-
-    }
 }
diff --git 
a/integration-tests-support/test-support/src/main/java/org/apache/camel/quarkus/test/EnabledIfFipsModeCondition.java
 
b/integration-tests-support/test-support/src/main/java/org/apache/camel/quarkus/test/FipsModeUtil.java
similarity index 54%
copy from 
integration-tests-support/test-support/src/main/java/org/apache/camel/quarkus/test/EnabledIfFipsModeCondition.java
copy to 
integration-tests-support/test-support/src/main/java/org/apache/camel/quarkus/test/FipsModeUtil.java
index f858c2b835..6878576e5e 100644
--- 
a/integration-tests-support/test-support/src/main/java/org/apache/camel/quarkus/test/EnabledIfFipsModeCondition.java
+++ 
b/integration-tests-support/test-support/src/main/java/org/apache/camel/quarkus/test/FipsModeUtil.java
@@ -18,46 +18,22 @@ package org.apache.camel.quarkus.test;
 
 import java.security.Provider;
 import java.security.Security;
+import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 
-import org.junit.jupiter.api.extension.ConditionEvaluationResult;
-import org.junit.jupiter.api.extension.ExecutionCondition;
-import org.junit.jupiter.api.extension.ExtensionContext;
+public class FipsModeUtil {
 
-import static 
org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled;
-import static 
org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled;
-import static org.junit.platform.commons.util.AnnotationUtils.findAnnotation;
-
-public class EnabledIfFipsModeCondition implements ExecutionCondition {
-    private static final ConditionEvaluationResult ENABLED_BY_DEFAULT = 
enabled("@EnabledIfFipsMode is not present");
-
-    @Override
-    public ConditionEvaluationResult 
evaluateExecutionCondition(ExtensionContext context) {
-        return findAnnotation(context.getElement(), 
EnabledIfFipsMode.class).map(this::map).orElse(ENABLED_BY_DEFAULT);
-    }
-
-    private ConditionEvaluationResult map(EnabledIfFipsMode annotation) {
-        List<String> providersToMatch = List.of(annotation.providers());
-        Optional<String> fipsProviders = findFipsProvider(providersToMatch);
-
-        if (fipsProviders == null) {
-            return disabled("No FIPS security providers were detected");
-        }
-        if (fipsProviders.isEmpty()) {
-            return enabled("Detected FIPS security providers");
-        }
-
-        return enabled("Detected FIPS security provider " + 
fipsProviders.get());
+    private FipsModeUtil() {
     }
 
     /**
      * Returns null if system is not in fips mode.
      * Returns Optional.empty if system is in fips mode and there is some 
provider containing "fips"
      * Returns Optional.name if system is in fips mode and there is a match 
with the provided providers
-     * (the last 2 options allows to differentiate reason of the 
enablement/disablement)
+     * (the last 2 options allows differentiate reason of the 
enablement/disablement)
      */
-    Optional<String> findFipsProvider(List<String> providersToMatch) {
+    static public Optional<String> findFipsProvider(List<String> 
providersToMatch) {
         Provider[] jdkProviders = Security.getProviders();
         int matchCount = 0;
 
@@ -74,6 +50,12 @@ public class EnabledIfFipsModeCondition implements 
ExecutionCondition {
         }
 
         return null;
+    }
 
+    /**
+     * Return true if system is in FIPS mode.
+     */
+    static public boolean isFipsMode() {
+        return findFipsProvider(Collections.emptyList()) != null;
     }
 }
diff --git a/integration-tests/kafka-sasl-ssl/pom.xml 
b/integration-tests/kafka-sasl-ssl/pom.xml
index 347cb2e0f4..d54554c9c4 100644
--- a/integration-tests/kafka-sasl-ssl/pom.xml
+++ b/integration-tests/kafka-sasl-ssl/pom.xml
@@ -74,6 +74,11 @@
             <artifactId>quarkus-junit4-mock</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            
<artifactId>camel-quarkus-integration-tests-support-certificate-generator</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <profiles>
diff --git 
a/integration-tests/kafka-sasl-ssl/src/test/java/org/apache/camel/quarkus/kafka/sasl/KafkaSaslSslTest.java
 
b/integration-tests/kafka-sasl-ssl/src/test/java/org/apache/camel/quarkus/kafka/sasl/KafkaSaslSslTest.java
index 947a7ee949..9c1fb307a0 100644
--- 
a/integration-tests/kafka-sasl-ssl/src/test/java/org/apache/camel/quarkus/kafka/sasl/KafkaSaslSslTest.java
+++ 
b/integration-tests/kafka-sasl-ssl/src/test/java/org/apache/camel/quarkus/kafka/sasl/KafkaSaslSslTest.java
@@ -22,10 +22,17 @@ import io.quarkus.test.common.QuarkusTestResource;
 import io.quarkus.test.junit.QuarkusTest;
 import io.restassured.RestAssured;
 import io.restassured.path.json.JsonPath;
+import me.escoffier.certs.Format;
+import me.escoffier.certs.junit5.Certificate;
+import org.apache.camel.quarkus.test.support.certificate.TestCertificates;
 import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
+@TestCertificates(certificates = {
+        @Certificate(name = KafkaSaslSslTestResource.KAFKA_HOSTNAME, formats = 
{
+                Format.PKCS12 }, password = 
KafkaSaslSslTestResource.KAFKA_KEYSTORE_PASSWORD)
+}, baseDir = KafkaSaslSslTestResource.CERTS_BASEDIR)
 @QuarkusTest
 @QuarkusTestResource(KafkaSaslSslTestResource.class)
 public class KafkaSaslSslTest {
diff --git 
a/integration-tests/kafka-sasl-ssl/src/test/java/org/apache/camel/quarkus/kafka/sasl/KafkaSaslSslTestResource.java
 
b/integration-tests/kafka-sasl-ssl/src/test/java/org/apache/camel/quarkus/kafka/sasl/KafkaSaslSslTestResource.java
index 3366526b23..7de0728de2 100644
--- 
a/integration-tests/kafka-sasl-ssl/src/test/java/org/apache/camel/quarkus/kafka/sasl/KafkaSaslSslTestResource.java
+++ 
b/integration-tests/kafka-sasl-ssl/src/test/java/org/apache/camel/quarkus/kafka/sasl/KafkaSaslSslTestResource.java
@@ -16,10 +16,7 @@
  */
 package org.apache.camel.quarkus.kafka.sasl;
 
-import java.io.IOException;
-import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Map;
 import java.util.stream.Stream;
@@ -27,77 +24,46 @@ import java.util.stream.Stream;
 import com.github.dockerjava.api.command.InspectContainerResponse;
 import io.strimzi.test.container.StrimziKafkaContainer;
 import org.apache.camel.quarkus.test.support.kafka.KafkaTestResource;
-import org.apache.camel.quarkus.test.support.kafka.KafkaTestSupport;
 import org.apache.camel.util.CollectionHelper;
-import org.apache.commons.io.FileUtils;
 import org.testcontainers.images.builder.Transferable;
 import org.testcontainers.utility.MountableFile;
 
 import static 
io.strimzi.test.container.StrimziZookeeperContainer.ZOOKEEPER_PORT;
 
 public class KafkaSaslSslTestResource extends KafkaTestResource {
-    private static final String KAFKA_KEYSTORE_FILE = "kafka-keystore.p12";
-    private static final String KAFKA_KEYSTORE_PASSWORD = "kafkas3cret";
-    private static final String KAFKA_KEYSTORE_TYPE = "PKCS12";
-    private static final String KAFKA_TRUSTSTORE_FILE = "kafka-truststore.p12";
-    private static final String KAFKA_CERTIFICATE_SCRIPT = 
"generate-certificates.sh";
-    private static Path configDir;
-    private SaslSslKafkaContainer container;
+    static final String KAFKA_KEYSTORE_PASSWORD = 
"n7BfLSrdIKZSd2SJv8pUvVurrOW6q2Q3G";
+    //min lengthe is 32 because of SCRAM-SHA-512
+    static final String ALICE_PASSWORD = "IuepUrtaAXpwgTy6TPmInRAUinlK2acQL";
+    static final String KAFKA_HOSTNAME = "localhost";
+    static final String CERTS_BASEDIR = "target/certs";
+
+    static final String KAFKA_KEYSTORE_FILE = KAFKA_HOSTNAME + "-keystore.p12";
+    static final String KAFKA_KEYSTORE_TYPE = "PKCS12";
+    static final String KAFKA_TRUSTSTORE_FILE = KAFKA_HOSTNAME + 
"-truststore.p12";
 
     @Override
     public Map<String, String> start() {
-        try {
-            configDir = Files.createTempDirectory("KafkaSaslSslTestResource-");
-            ClassLoader classLoader = 
Thread.currentThread().getContextClassLoader();
-            Stream.of("kafka_server_jaas.conf", KAFKA_KEYSTORE_FILE, 
KAFKA_TRUSTSTORE_FILE)
-                    .forEach(fileName -> {
-                        try (InputStream in = 
classLoader.getResourceAsStream("config/" + fileName)) {
-                            Files.copy(in, configDir.resolve(fileName));
-                        } catch (IOException e) {
-                            throw new RuntimeException(e);
-                        }
-                    });
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-
-        KafkaTestSupport.regenerateCertificatesForDockerHost(configDir, 
KAFKA_CERTIFICATE_SCRIPT, KAFKA_KEYSTORE_FILE,
-                KAFKA_TRUSTSTORE_FILE);
-
-        container = new SaslSslKafkaContainer(KAFKA_IMAGE_NAME);
-        container.waitForRunning();
-        container.start();
+        String bootstrapServers = start(name -> new 
SaslSslKafkaContainer(name));
 
         String jaasConfig = 
"org.apache.kafka.common.security.scram.ScramLoginModule required "
                 + "username=\"alice\" "
-                + "password=\"alice-secret\";";
+                + "password=\"" + ALICE_PASSWORD + "\";";
 
         return CollectionHelper.mapOf(
-                "camel.component.kafka.brokers", 
container.getBootstrapServers(),
+                "camel.component.kafka.brokers", bootstrapServers,
                 "camel.component.kafka.sasl-mechanism", "SCRAM-SHA-512",
                 "camel.component.kafka.sasl-jaas-config", jaasConfig,
                 "camel.component.kafka.security-protocol", "SASL_SSL",
                 "camel.component.kafka.ssl-key-password", 
KAFKA_KEYSTORE_PASSWORD,
-                "camel.component.kafka.ssl-keystore-location", 
configDir.resolve(KAFKA_KEYSTORE_FILE).toString(),
+                "camel.component.kafka.ssl-keystore-location", 
Path.of(CERTS_BASEDIR).resolve(KAFKA_KEYSTORE_FILE).toString(),
                 "camel.component.kafka.ssl-keystore-password", 
KAFKA_KEYSTORE_PASSWORD,
                 "camel.component.kafka.ssl-keystore-type", KAFKA_KEYSTORE_TYPE,
-                "camel.component.kafka.ssl-truststore-location", 
configDir.resolve(KAFKA_TRUSTSTORE_FILE).toString(),
+                "camel.component.kafka.ssl-truststore-location",
+                
Path.of(CERTS_BASEDIR).resolve(KAFKA_TRUSTSTORE_FILE).toString(),
                 "camel.component.kafka.ssl-truststore-password", 
KAFKA_KEYSTORE_PASSWORD,
                 "camel.component.kafka.ssl-truststore-type", 
KAFKA_KEYSTORE_TYPE);
     }
 
-    @Override
-    public void stop() {
-        if (this.container != null) {
-            try {
-                this.container.stop();
-                FileUtils.deleteDirectory(configDir.toFile());
-            } catch (Exception e) {
-                // Ignored
-            }
-        }
-    }
-
     // KafkaContainer does not support SASL SSL OOTB so we need some 
customizations
     static final class SaslSslKafkaContainer extends StrimziKafkaContainer {
         SaslSslKafkaContainer(final String dockerImageName) {
@@ -143,17 +109,15 @@ public class KafkaSaslSslTestResource extends 
KafkaTestResource {
 
             Stream.of(KAFKA_KEYSTORE_FILE, KAFKA_TRUSTSTORE_FILE)
                     .forEach(keyStoreFile -> {
-                        try {
-                            
copyFileToContainer(Transferable.of(Files.readAllBytes(configDir.resolve(keyStoreFile))),
-                                    "/etc/kafka/secrets/" + keyStoreFile);
-                        } catch (IOException e) {
-                            throw new RuntimeException(e);
-                        }
+                        copyFileToContainer(
+                                
MountableFile.forHostPath(Path.of(CERTS_BASEDIR).resolve(keyStoreFile)),
+                                "/etc/kafka/secrets/" + keyStoreFile);
                     });
 
             String setupUsersScript = "#!/bin/bash\n"
                     + "KAFKA_OPTS= /opt/kafka/bin/kafka-configs.sh --zookeeper 
localhost:" + ZOOKEEPER_PORT
-                    + " --alter --add-config 
'SCRAM-SHA-512=[iterations=8192,password=alice-secret]' --entity-type users 
--entity-name alice";
+                    + " --alter --add-config 
'SCRAM-SHA-512=[iterations=8192,password=" + ALICE_PASSWORD
+                    + "]' --entity-type users --entity-name alice";
 
             copyFileToContainer(
                     
Transferable.of(setupUsersScript.getBytes(StandardCharsets.UTF_8), 0775),
diff --git 
a/integration-tests/kafka-sasl-ssl/src/test/resources/config/generate-certificates.sh
 
b/integration-tests/kafka-sasl-ssl/src/test/resources/config/generate-certificates.sh
deleted file mode 100755
index baabd055ab..0000000000
--- 
a/integration-tests/kafka-sasl-ssl/src/test/resources/config/generate-certificates.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You 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
-#
-#      http://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.
-#
-
-
-rm -f *.p12
-
-export CN=${1:-localhost}
-export SUBJECT_ALT_NAMES=${2:-"DNS:localhost,IP:127.0.0.1"}
-export SECRET=kafkas3cret
-export JKS_FILE=kafka-keystore.jks
-export JKS_TRUST_FILE=kafka-truststore.jks
-export CERT_FILE=localhost.crt
-export PKCS_FILE=kafka-keystore.p12
-export PKCS_TRUST_FILE=kafka-truststore.p12
-export PEM_FILE_CERT=kafka-cert.pem
-export PEM_FILE_KEY=kafka-key.pem
-
-keytool -genkey -alias kafka-test-store -keyalg RSA -keystore ${JKS_FILE} 
-keysize 2048 -validity 3650 -ext "san=${SUBJECT_ALT_NAMES}" -dname CN=${CN} 
-keypass ${SECRET} -storepass ${SECRET}
-keytool -export -alias kafka-test-store -file ${CERT_FILE} -keystore 
${JKS_FILE} -keypass ${SECRET} -storepass ${SECRET}
-keytool -importkeystore -srckeystore ${JKS_FILE} -srcstorepass ${SECRET} 
-destkeystore ${PKCS_FILE} -deststoretype PKCS12 -deststorepass ${SECRET}
-keytool -keystore ${JKS_TRUST_FILE} -import -file ${CERT_FILE} -keypass 
${SECRET} -storepass ${SECRET} -noprompt
-keytool -importkeystore -srckeystore ${JKS_TRUST_FILE} -srcstorepass ${SECRET} 
-destkeystore ${PKCS_TRUST_FILE} -deststoretype PKCS12 -deststorepass ${SECRET}
-
-rm -f *.crt *.jks
diff --git 
a/integration-tests/kafka-sasl-ssl/src/test/resources/config/kafka-keystore.p12 
b/integration-tests/kafka-sasl-ssl/src/test/resources/config/kafka-keystore.p12
deleted file mode 100644
index 2585d2eee3..0000000000
Binary files 
a/integration-tests/kafka-sasl-ssl/src/test/resources/config/kafka-keystore.p12 
and /dev/null differ
diff --git 
a/integration-tests/kafka-sasl-ssl/src/test/resources/config/kafka-truststore.p12
 
b/integration-tests/kafka-sasl-ssl/src/test/resources/config/kafka-truststore.p12
deleted file mode 100644
index c124e2113c..0000000000
Binary files 
a/integration-tests/kafka-sasl-ssl/src/test/resources/config/kafka-truststore.p12
 and /dev/null differ
diff --git 
a/integration-tests/kafka-sasl-ssl/src/test/resources/config/kafka_server_jaas.conf
 
b/integration-tests/kafka-sasl-ssl/src/test/resources/config/kafka_server_jaas.conf
index 4cd805f26a..1603da8ebc 100644
--- 
a/integration-tests/kafka-sasl-ssl/src/test/resources/config/kafka_server_jaas.conf
+++ 
b/integration-tests/kafka-sasl-ssl/src/test/resources/config/kafka_server_jaas.conf
@@ -1,7 +1,4 @@
 KafkaServer {
    org.apache.kafka.common.security.scram.ScramLoginModule required
-  username="admin"
-  password="admin-secret"
-  user_admin="admin-secret"
-  user_alice="alice-secret";
+  user_alice="IuepUrtaAXpwgTy6TPmInRAUinlK2acQL";
 };
\ No newline at end of file
diff --git 
a/integration-tests/kafka-sasl/src/test/java/org/apache/camel/quarkus/kafka/sasl/KafkaSaslBindingTest.java
 
b/integration-tests/kafka-sasl/src/test/java/org/apache/camel/quarkus/kafka/sasl/KafkaSaslBindingTest.java
index c4a246b13b..07c229427a 100644
--- 
a/integration-tests/kafka-sasl/src/test/java/org/apache/camel/quarkus/kafka/sasl/KafkaSaslBindingTest.java
+++ 
b/integration-tests/kafka-sasl/src/test/java/org/apache/camel/quarkus/kafka/sasl/KafkaSaslBindingTest.java
@@ -22,10 +22,12 @@ import io.quarkus.test.common.QuarkusTestResource;
 import io.quarkus.test.junit.QuarkusTest;
 import io.restassured.RestAssured;
 import io.restassured.path.json.JsonPath;
+import org.apache.camel.quarkus.test.DisabledIfFipsMode;
 import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
 
+@DisabledIfFipsMode
 @QuarkusTest
 @QuarkusTestResource(KafkaSaslTestResource.class)
 public class KafkaSaslBindingTest {
diff --git a/integration-tests/kafka-ssl/pom.xml 
b/integration-tests/kafka-ssl/pom.xml
index b06b83ede8..b64451e28c 100644
--- a/integration-tests/kafka-ssl/pom.xml
+++ b/integration-tests/kafka-ssl/pom.xml
@@ -78,6 +78,11 @@
             <artifactId>quarkus-junit4-mock</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            
<artifactId>camel-quarkus-integration-tests-support-certificate-generator</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <profiles>
diff --git 
a/integration-tests/kafka-ssl/src/test/java/org/apache/camel/quarkus/kafka/ssl/KafkaSslTest.java
 
b/integration-tests/kafka-ssl/src/test/java/org/apache/camel/quarkus/kafka/ssl/KafkaSslTest.java
index 8cc3a89696..0921d58d97 100644
--- 
a/integration-tests/kafka-ssl/src/test/java/org/apache/camel/quarkus/kafka/ssl/KafkaSslTest.java
+++ 
b/integration-tests/kafka-ssl/src/test/java/org/apache/camel/quarkus/kafka/ssl/KafkaSslTest.java
@@ -16,23 +16,33 @@
  */
 package org.apache.camel.quarkus.kafka.ssl;
 
+import java.lang.reflect.AnnotatedElement;
 import java.util.UUID;
 
 import io.quarkus.test.common.QuarkusTestResource;
 import io.quarkus.test.junit.QuarkusTest;
 import io.restassured.RestAssured;
 import io.restassured.path.json.JsonPath;
+import me.escoffier.certs.Format;
+import me.escoffier.certs.junit5.Certificate;
+import org.apache.camel.quarkus.test.support.certificate.TestCertificates;
 import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.hamcrest.Matchers.is;
 
+@TestCertificates(certificates = {
+        @Certificate(name = KafkaSslTestResource.KAFKA_HOSTNAME, formats = {
+                Format.PKCS12 }, password = 
KafkaSslTestResource.KAFKA_KEYSTORE_PASSWORD)
+}, baseDir = KafkaSslTestResource.CERTS_BASEDIR)
 @QuarkusTest
 @QuarkusTestResource(KafkaSslTestResource.class)
 public class KafkaSslTest {
 
     @Test
     void testKafkaBridge() {
+        AnnotatedElement ae;
+
         String body = UUID.randomUUID().toString();
 
         RestAssured.given()
diff --git 
a/integration-tests/kafka-ssl/src/test/java/org/apache/camel/quarkus/kafka/ssl/KafkaSslTestResource.java
 
b/integration-tests/kafka-ssl/src/test/java/org/apache/camel/quarkus/kafka/ssl/KafkaSslTestResource.java
index 01269fb7ad..2f7a767eb3 100644
--- 
a/integration-tests/kafka-ssl/src/test/java/org/apache/camel/quarkus/kafka/ssl/KafkaSslTestResource.java
+++ 
b/integration-tests/kafka-ssl/src/test/java/org/apache/camel/quarkus/kafka/ssl/KafkaSslTestResource.java
@@ -16,9 +16,6 @@
  */
 package org.apache.camel.quarkus.kafka.ssl;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Map;
 import java.util.stream.Stream;
@@ -26,70 +23,39 @@ import java.util.stream.Stream;
 import com.github.dockerjava.api.command.InspectContainerResponse;
 import io.strimzi.test.container.StrimziKafkaContainer;
 import org.apache.camel.quarkus.test.support.kafka.KafkaTestResource;
-import org.apache.camel.quarkus.test.support.kafka.KafkaTestSupport;
 import org.apache.camel.util.CollectionHelper;
-import org.apache.commons.io.FileUtils;
 import org.apache.kafka.clients.CommonClientConfigs;
-import org.testcontainers.images.builder.Transferable;
+import org.testcontainers.utility.MountableFile;
 
 public class KafkaSslTestResource extends KafkaTestResource {
-    private static final String KAFKA_KEYSTORE_FILE = "kafka-keystore.p12";
-    private static final String KAFKA_KEYSTORE_PASSWORD = "kafkas3cret";
-    private static final String KAFKA_KEYSTORE_TYPE = "PKCS12";
-    private static final String KAFKA_TRUSTSTORE_FILE = "kafka-truststore.p12";
-    private static final String KAFKA_CERTIFICATE_SCRIPT = 
"generate-certificates.sh";
-    private static Path configDir;
-    private SSLKafkaContainer container;
+
+    static final String KAFKA_KEYSTORE_PASSWORD = 
"PAG4i8511xp1lzVu585foRLjD4v62yBS";
+    static final String KAFKA_HOSTNAME = "localhost";
+    static final String CERTS_BASEDIR = "target/certs";
+
+    static final String KAFKA_KEYSTORE_FILE = KAFKA_HOSTNAME + "-keystore.p12";
+    static final String KAFKA_KEYSTORE_TYPE = "PKCS12";
+    static final String KAFKA_TRUSTSTORE_FILE = KAFKA_HOSTNAME + 
"-truststore.p12";
 
     @Override
     public Map<String, String> start() {
-        try {
-            configDir = Files.createTempDirectory("KafkaSaslSslTestResource-");
-            ClassLoader classLoader = 
Thread.currentThread().getContextClassLoader();
-            Stream.of(KAFKA_KEYSTORE_FILE, KAFKA_TRUSTSTORE_FILE)
-                    .forEach(fileName -> {
-                        try (InputStream in = 
classLoader.getResourceAsStream("config/" + fileName)) {
-                            Files.copy(in, configDir.resolve(fileName));
-                        } catch (IOException e) {
-                            throw new RuntimeException(e);
-                        }
-                    });
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
 
-        KafkaTestSupport.regenerateCertificatesForDockerHost(configDir, 
KAFKA_CERTIFICATE_SCRIPT, KAFKA_KEYSTORE_FILE,
-                KAFKA_TRUSTSTORE_FILE);
-
-        container = new SSLKafkaContainer(KAFKA_IMAGE_NAME);
-        container.waitForRunning();
-        container.start();
+        String bootstrapServers = start(name -> new SSLKafkaContainer(name));
 
         return CollectionHelper.mapOf(
-                "kafka." + CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG, 
container.getBootstrapServers(),
-                "camel.component.kafka.brokers", 
container.getBootstrapServers(),
+                "kafka." + CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG, 
bootstrapServers,
+                "camel.component.kafka.brokers", bootstrapServers,
                 "camel.component.kafka.security-protocol", "SSL",
                 "camel.component.kafka.ssl-key-password", 
KAFKA_KEYSTORE_PASSWORD,
-                "camel.component.kafka.ssl-keystore-location", 
configDir.resolve(KAFKA_KEYSTORE_FILE).toString(),
+                "camel.component.kafka.ssl-keystore-location", 
Path.of(CERTS_BASEDIR).resolve(KAFKA_KEYSTORE_FILE).toString(),
                 "camel.component.kafka.ssl-keystore-password", 
KAFKA_KEYSTORE_PASSWORD,
                 "camel.component.kafka.ssl-keystore-type", KAFKA_KEYSTORE_TYPE,
-                "camel.component.kafka.ssl-truststore-location", 
configDir.resolve(KAFKA_TRUSTSTORE_FILE).toString(),
+                "camel.component.kafka.ssl-truststore-location",
+                
Path.of(CERTS_BASEDIR).resolve(KAFKA_TRUSTSTORE_FILE).toString(),
                 "camel.component.kafka.ssl-truststore-password", 
KAFKA_KEYSTORE_PASSWORD,
                 "camel.component.kafka.ssl-truststore-type", 
KAFKA_KEYSTORE_TYPE);
     }
 
-    @Override
-    public void stop() {
-        if (this.container != null) {
-            try {
-                this.container.stop();
-                FileUtils.deleteDirectory(configDir.toFile());
-            } catch (Exception e) {
-                // Ignored
-            }
-        }
-    }
-
     // KafkaContainer does not support SSL OOTB so we need some customizations
     static final class SSLKafkaContainer extends StrimziKafkaContainer {
         SSLKafkaContainer(final String dockerImageName) {
@@ -117,6 +83,7 @@ public class KafkaSslTestResource extends KafkaTestResource {
                     Map.entry("ssl.truststore.type", KAFKA_KEYSTORE_TYPE),
                     Map.entry("ssl.endpoint.identification.algorithm", ""));
 
+            withEnv("STRIMZI_TEST_ROOT_LOG_LEVEL", "DEBUG");
             withBrokerId(1);
             withKafkaConfigurationMap(config);
             withLogConsumer(frame -> System.out.print(frame.getUtf8String()));
@@ -128,12 +95,9 @@ public class KafkaSslTestResource extends KafkaTestResource 
{
 
             Stream.of(KAFKA_KEYSTORE_FILE, KAFKA_TRUSTSTORE_FILE)
                     .forEach(keyStoreFile -> {
-                        try {
-                            
copyFileToContainer(Transferable.of(Files.readAllBytes(configDir.resolve(keyStoreFile))),
-                                    "/etc/kafka/secrets/" + keyStoreFile);
-                        } catch (IOException e) {
-                            throw new RuntimeException(e);
-                        }
+                        copyFileToContainer(
+                                
MountableFile.forHostPath(Path.of(CERTS_BASEDIR).resolve(keyStoreFile)),
+                                "/etc/kafka/secrets/" + keyStoreFile);
                     });
         }
     }
diff --git 
a/integration-tests/kafka-ssl/src/test/resources/config/generate-certificates.sh
 
b/integration-tests/kafka-ssl/src/test/resources/config/generate-certificates.sh
deleted file mode 100755
index baabd055ab..0000000000
--- 
a/integration-tests/kafka-ssl/src/test/resources/config/generate-certificates.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You 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
-#
-#      http://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.
-#
-
-
-rm -f *.p12
-
-export CN=${1:-localhost}
-export SUBJECT_ALT_NAMES=${2:-"DNS:localhost,IP:127.0.0.1"}
-export SECRET=kafkas3cret
-export JKS_FILE=kafka-keystore.jks
-export JKS_TRUST_FILE=kafka-truststore.jks
-export CERT_FILE=localhost.crt
-export PKCS_FILE=kafka-keystore.p12
-export PKCS_TRUST_FILE=kafka-truststore.p12
-export PEM_FILE_CERT=kafka-cert.pem
-export PEM_FILE_KEY=kafka-key.pem
-
-keytool -genkey -alias kafka-test-store -keyalg RSA -keystore ${JKS_FILE} 
-keysize 2048 -validity 3650 -ext "san=${SUBJECT_ALT_NAMES}" -dname CN=${CN} 
-keypass ${SECRET} -storepass ${SECRET}
-keytool -export -alias kafka-test-store -file ${CERT_FILE} -keystore 
${JKS_FILE} -keypass ${SECRET} -storepass ${SECRET}
-keytool -importkeystore -srckeystore ${JKS_FILE} -srcstorepass ${SECRET} 
-destkeystore ${PKCS_FILE} -deststoretype PKCS12 -deststorepass ${SECRET}
-keytool -keystore ${JKS_TRUST_FILE} -import -file ${CERT_FILE} -keypass 
${SECRET} -storepass ${SECRET} -noprompt
-keytool -importkeystore -srckeystore ${JKS_TRUST_FILE} -srcstorepass ${SECRET} 
-destkeystore ${PKCS_TRUST_FILE} -deststoretype PKCS12 -deststorepass ${SECRET}
-
-rm -f *.crt *.jks
diff --git 
a/integration-tests/kafka-ssl/src/test/resources/config/kafka-keystore.p12 
b/integration-tests/kafka-ssl/src/test/resources/config/kafka-keystore.p12
deleted file mode 100644
index 2585d2eee3..0000000000
Binary files 
a/integration-tests/kafka-ssl/src/test/resources/config/kafka-keystore.p12 and 
/dev/null differ
diff --git 
a/integration-tests/kafka-ssl/src/test/resources/config/kafka-truststore.p12 
b/integration-tests/kafka-ssl/src/test/resources/config/kafka-truststore.p12
deleted file mode 100644
index c124e2113c..0000000000
Binary files 
a/integration-tests/kafka-ssl/src/test/resources/config/kafka-truststore.p12 
and /dev/null differ
diff --git a/pom.xml b/pom.xml
index 8bb4cc0adc..4021aa4687 100644
--- a/pom.xml
+++ b/pom.xml
@@ -169,6 +169,7 @@
         <zookeeper.version>${zookeeper-version}</zookeeper.version>
 
         <!-- Test dependency versions (keep sorted alphabetically) -->
+        <certificate.generator.version>0.5.0</certificate.generator.version>
         <consul-client.version>${consul-client-version}</consul-client.version>
         <ftpserver.version>${ftpserver-version}</ftpserver.version>
         <hamcrest.version>2.2</hamcrest.version><!-- Awaitility and Wiremock 
-->
diff --git a/poms/bom-test/pom.xml b/poms/bom-test/pom.xml
index 1bdcfc59a1..908cbe12a0 100644
--- a/poms/bom-test/pom.xml
+++ b/poms/bom-test/pom.xml
@@ -81,6 +81,11 @@
                 <artifactId>quarkus-micrometer-registry-jmx</artifactId>
                 <version>${quarkiverse-micrometer.version}</version>
             </dependency>
+            <dependency>
+                <groupId>me.escoffier.certs</groupId>
+                <artifactId>certificate-generator-junit5</artifactId>
+                <version>${certificate.generator.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.apache.camel.quarkus</groupId>
                 
<artifactId>camel-quarkus-integration-test-support-custom-dataformat</artifactId>
@@ -149,6 +154,11 @@
                 <version>${camel-quarkus.version}</version>
                 <type>test-jar</type>
             </dependency>
+            <dependency>
+                <groupId>org.apache.camel.quarkus</groupId>
+                
<artifactId>camel-quarkus-integration-tests-support-certificate-generator</artifactId>
+                <version>${camel-quarkus.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.apache.camel.quarkus</groupId>
                 
<artifactId>camel-quarkus-integration-tests-support-kafka</artifactId>

Reply via email to