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

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

commit ed3e429ceaf6554defe62a99edb92c53177b44b1
Author: Gaelle Fournier <[email protected]>
AuthorDate: Thu Apr 16 18:36:35 2026 +0200

    feat: Add Camel SFTP Host Certificate Verification
---
 .../component/ftp/deployment/FtpProcessor.java     |  17 +++
 .../support/sftp/SftpHostCertTestResource.java     | 170 +++++++++++++++++++++
 .../quarkus/component/sftp/it/SftpResource.java    | 114 ++++++++++++++
 .../ftp/src/main/resources/application.properties  |   2 +-
 .../main/resources/certs/generate-certificates.sh  |  66 ++++++--
 .../ftp/src/main/resources/certs/host-ca.pub       |   1 +
 .../src/main/resources/certs/host-key-rsa-cert.pub |   1 +
 .../ftp/src/main/resources/certs/host-key-rsa.key  |  27 ++++
 .../src/main/resources/certs/test-key-rsa-cert.pub |   2 +-
 .../ftp/src/main/resources/certs/test-key-rsa.key  |  48 +++---
 .../quarkus/component/sftp/it/SftpHostCertIT.java  |  18 +--
 .../component/sftp/it/SftpHostCertTest.java        |  78 ++++++++++
 12 files changed, 493 insertions(+), 51 deletions(-)

diff --git 
a/extensions/ftp/deployment/src/main/java/org/apache/camel/quarkus/component/ftp/deployment/FtpProcessor.java
 
b/extensions/ftp/deployment/src/main/java/org/apache/camel/quarkus/component/ftp/deployment/FtpProcessor.java
index 218c96e6f6..967123e502 100644
--- 
a/extensions/ftp/deployment/src/main/java/org/apache/camel/quarkus/component/ftp/deployment/FtpProcessor.java
+++ 
b/extensions/ftp/deployment/src/main/java/org/apache/camel/quarkus/component/ftp/deployment/FtpProcessor.java
@@ -18,6 +18,7 @@ package org.apache.camel.quarkus.component.ftp.deployment;
 
 import io.quarkus.deployment.annotations.BuildStep;
 import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
 
 class FtpProcessor {
 
@@ -27,4 +28,20 @@ class FtpProcessor {
     FeatureBuildItem feature() {
         return new FeatureBuildItem(FEATURE);
     }
+
+    @BuildStep
+    ReflectiveClassBuildItem registerJSchCertificateClasses() {
+        // JSch OpenSSH certificate support classes for @cert-authority 
parsing in known_hosts
+        // The quarkus-jsch reflection config is missing several classes that 
JSch loads dynamically.
+        return ReflectiveClassBuildItem.builder(
+                "com.jcraft.jsch.KeyPairRSA",
+                "com.jcraft.jsch.KeyPairECDSA",
+                "com.jcraft.jsch.KeyPairEd25519",
+                "com.jcraft.jsch.KeyPairEd448",
+                "com.jcraft.jsch.KeyPairDSA",
+                "com.jcraft.jsch.SignatureRSA",
+                "com.jcraft.jsch.SignatureECDSA",
+                "com.jcraft.jsch.jce.SignatureEd25519")
+                .build();
+    }
 }
diff --git 
a/integration-tests-support/sftp/src/main/java/org/apache/camel/quarkus/test/support/sftp/SftpHostCertTestResource.java
 
b/integration-tests-support/sftp/src/main/java/org/apache/camel/quarkus/test/support/sftp/SftpHostCertTestResource.java
new file mode 100644
index 0000000000..1f45db0327
--- /dev/null
+++ 
b/integration-tests-support/sftp/src/main/java/org/apache/camel/quarkus/test/support/sftp/SftpHostCertTestResource.java
@@ -0,0 +1,170 @@
+/*
+ * 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.sftp;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.KeyPair;
+import java.security.PublicKey;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
+import org.apache.camel.quarkus.test.AvailablePortFinder;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.config.keys.OpenSshCertificate;
+import org.apache.sshd.common.config.keys.PublicKeyEntry;
+import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory;
+import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
+import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.apache.sshd.common.signature.BuiltinSignatures;
+import org.apache.sshd.common.signature.Signature;
+import org.apache.sshd.scp.server.ScpCommandFactory;
+import org.apache.sshd.server.SshServer;
+import org.apache.sshd.sftp.server.SftpSubsystemFactory;
+import org.jboss.logging.Logger;
+
+/**
+ * SFTP test resource that presents host certificates for host certificate 
verification testing.
+ * This is separate from SftpTestResource to avoid interfering with other 
tests.
+ */
+public class SftpHostCertTestResource implements 
QuarkusTestResourceLifecycleManager {
+    private static final Logger LOGGER = 
Logger.getLogger(SftpHostCertTestResource.class);
+
+    private SshServer sshServer;
+    private Path sftpHome;
+
+    @Override
+    public Map<String, String> start() {
+        try {
+            final int port = AvailablePortFinder.getNextAvailable();
+
+            sftpHome = Files.createTempDirectory("sftp-hostcert-");
+            Path adminHome = sftpHome.resolve("admin");
+            Files.createDirectories(adminHome);
+
+            VirtualFileSystemFactory factory = new VirtualFileSystemFactory();
+            factory.setUserHomeDir("admin", adminHome.toAbsolutePath());
+
+            sshServer = SshServer.setUpDefaultServer();
+            sshServer.setPort(port);
+
+            sshServer.setKeyPairProvider(createHostCertKeyPairProvider());
+
+            sshServer.setSubsystemFactories(Collections.singletonList(new 
SftpSubsystemFactory()));
+            sshServer.setCommandFactory(new ScpCommandFactory());
+            sshServer.setPasswordAuthenticator((username, password, session) 
-> true);
+            sshServer.setPublickeyAuthenticator((username, key, session) -> 
true);
+
+            // Add certificate signature factories
+            List<NamedFactory<Signature>> signatureFactories = 
sshServer.getSignatureFactories();
+            signatureFactories.add(BuiltinSignatures.rsa_cert);
+            signatureFactories.add(BuiltinSignatures.rsaSHA256_cert);
+            signatureFactories.add(BuiltinSignatures.rsaSHA512_cert);
+            signatureFactories.add(BuiltinSignatures.ed25519_cert);
+            sshServer.setSignatureFactories(signatureFactories);
+
+            sshServer.setFileSystemFactory(factory);
+            sshServer.start();
+
+            LOGGER.infof("SFTP server with host certificate started on port 
%d", port);
+
+            return Collections.singletonMap("camel.sftp.hostcert.test-port", 
Integer.toString(port));
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to start SFTP server with host 
certificate", e);
+        }
+    }
+
+    @Override
+    public void stop() {
+        try {
+            if (sshServer != null) {
+                sshServer.stop();
+                LOGGER.info("SFTP server with host certificate stopped");
+            }
+        } catch (Exception e) {
+            LOGGER.warn("Failed to stop SFTP server", e);
+        }
+
+        try {
+            if (sftpHome != null && Files.exists(sftpHome)) {
+                Files.walk(sftpHome)
+                        .sorted((a, b) -> -a.compareTo(b))
+                        .forEach(path -> {
+                            try {
+                                Files.delete(path);
+                            } catch (Exception e) {
+                                LOGGER.warn("Failed to delete SFTPHome file", 
e);
+                            }
+                        });
+            }
+        } catch (Exception e) {
+            LOGGER.warnf("Failed to delete sftp home: %s, %s", sftpHome, e);
+        }
+
+        AvailablePortFinder.releaseReservedPorts();
+    }
+
+    /**
+     * Creates a KeyPairProvider that wraps the host private key with the 
OpenSSH host certificate.
+     */
+    private static KeyPairProvider createHostCertKeyPairProvider() {
+        try {
+            // Load host private key from classpath (works in both JVM and 
native mode)
+            ClassLoader classLoader = 
Thread.currentThread().getContextClassLoader();
+
+            // Write host key to temp file (FileKeyPairProvider needs a file 
path)
+            Path tempHostKey = Files.createTempFile("host-key-rsa", ".key");
+            try (var keyStream = 
classLoader.getResourceAsStream("certs/host-key-rsa.key")) {
+                if (keyStream == null) {
+                    throw new IllegalStateException("Host key resource not 
found: certs/host-key-rsa.key");
+                }
+                Files.write(tempHostKey, keyStream.readAllBytes());
+            }
+
+            FileKeyPairProvider keyProvider = new 
FileKeyPairProvider(tempHostKey);
+            KeyPair originalKeyPair = 
keyProvider.loadKeys(null).iterator().next();
+
+            // Load host certificate from classpath
+            String certLine;
+            try (var certStream = 
classLoader.getResourceAsStream("certs/host-key-rsa-cert.pub")) {
+                if (certStream == null) {
+                    throw new IllegalStateException("Host certificate resource 
not found: certs/host-key-rsa-cert.pub");
+                }
+                certLine = new String(certStream.readAllBytes()).trim();
+            }
+
+            PublicKey certKey = 
PublicKeyEntry.parsePublicKeyEntry(certLine).resolvePublicKey(null, null, null);
+
+            if (!(certKey instanceof OpenSshCertificate)) {
+                throw new IllegalStateException("Host certificate file does 
not contain an OpenSSH certificate");
+            }
+
+            // Create a key pair with the certificate as the public key
+            KeyPair certKeyPair = new KeyPair(certKey, 
originalKeyPair.getPrivate());
+
+            // Clean up temp file
+            Files.deleteIfExists(tempHostKey);
+
+            return KeyPairProvider.wrap(certKeyPair);
+
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to load host certificate key 
pair", e);
+        }
+    }
+}
diff --git 
a/integration-tests/ftp/src/main/java/org/apache/camel/quarkus/component/sftp/it/SftpResource.java
 
b/integration-tests/ftp/src/main/java/org/apache/camel/quarkus/component/sftp/it/SftpResource.java
index 14de2c50c5..0a890acd93 100644
--- 
a/integration-tests/ftp/src/main/java/org/apache/camel/quarkus/component/sftp/it/SftpResource.java
+++ 
b/integration-tests/ftp/src/main/java/org/apache/camel/quarkus/component/sftp/it/SftpResource.java
@@ -225,4 +225,118 @@ public class SftpResource {
                 TIMEOUT_MS,
                 String.class);
     }
+
+    @Path("/hostcert/create/{fileName}")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    public Response createFileWithHostCertVerification(@PathParam("fileName") 
String fileName, String fileContent)
+            throws Exception {
+        String knownHostsFile = createHostCaKnownHostsFile();
+        String port = 
context.resolvePropertyPlaceholders("{{camel.sftp.hostcert.test-port}}");
+        String uri = "sftp://admin@localhost:"; + port
+                + 
"/sftp?password=admin&strictHostKeyChecking=yes&useUserKnownHostsFile=false&caSignatureAlgorithms=ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa&knownHostsFile="
+                + knownHostsFile;
+        producerTemplate.sendBodyAndHeader(uri, fileContent, 
Exchange.FILE_NAME, fileName);
+        return Response
+                .created(new URI("https://camel.apache.org/";))
+                .build();
+    }
+
+    @Path("/hostcert/get/{fileName}")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public String getFileWithHostCertVerification(@PathParam("fileName") 
String fileName) throws Exception {
+        String knownHostsFile = createHostCaKnownHostsFile();
+        return consumerTemplate.receiveBody(
+                
"sftp://admin@localhost:{{camel.sftp.hostcert.test-port}}/sftp?password=admin&strictHostKeyChecking=yes&useUserKnownHostsFile=false&caSignatureAlgorithms=ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa&knownHostsFile=";
+                        + knownHostsFile + 
"&localWorkDirectory=target&fileName=" + fileName,
+                TIMEOUT_MS,
+                String.class);
+    }
+
+    @Path("/hostcert/delete/{fileName}")
+    @DELETE
+    public Response deleteFileWithHostCert(@PathParam("fileName") String 
fileName) throws Exception {
+        String knownHostsFile = createHostCaKnownHostsFile();
+        consumerTemplate.receiveBody(
+                
"sftp://admin@localhost:{{camel.sftp.hostcert.test-port}}/sftp?password=admin&strictHostKeyChecking=yes&useUserKnownHostsFile=false&caSignatureAlgorithms=ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa&knownHostsFile=";
+                        + knownHostsFile + "&delete=true&fileName=" + fileName,
+                TIMEOUT_MS,
+                String.class);
+        return Response.noContent().build();
+    }
+
+    @Path("/hostcertWithAlgorithms/create/{fileName}")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    public Response createFileWithHostCertAndAlgorithms(@PathParam("fileName") 
String fileName, String fileContent)
+            throws Exception {
+        String knownHostsFile = createHostCaKnownHostsFile();
+        producerTemplate.sendBodyAndHeader(
+                
"sftp://admin@localhost:{{camel.sftp.hostcert.test-port}}/sftp?password=admin&strictHostKeyChecking=yes&useUserKnownHostsFile=false&knownHostsFile=";
+                        + knownHostsFile + 
"&caSignatureAlgorithms=ssh-ed25519,rsa-sha2-512,rsa-sha2-256",
+                fileContent,
+                Exchange.FILE_NAME, fileName);
+        return Response
+                .created(new URI("https://camel.apache.org/";))
+                .build();
+    }
+
+    @Path("/hostcertWithAlgorithms/get/{fileName}")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public String getFileWithHostCertAndAlgorithms(@PathParam("fileName") 
String fileName) throws Exception {
+        String knownHostsFile = createHostCaKnownHostsFile();
+        return consumerTemplate.receiveBody(
+                
"sftp://admin@localhost:{{camel.sftp.hostcert.test-port}}/sftp?password=admin&strictHostKeyChecking=yes&useUserKnownHostsFile=false&knownHostsFile=";
+                        + knownHostsFile
+                        + 
"&caSignatureAlgorithms=ssh-ed25519,rsa-sha2-512,rsa-sha2-256&localWorkDirectory=target&fileName="
+                        + fileName,
+                TIMEOUT_MS,
+                String.class);
+    }
+
+    @Path("/hostcertWithAlgorithms/delete/{fileName}")
+    @DELETE
+    public Response deleteFileWithHostCertAndAlgorithms(@PathParam("fileName") 
String fileName) throws Exception {
+        String knownHostsFile = createHostCaKnownHostsFile();
+        consumerTemplate.receiveBody(
+                
"sftp://admin@localhost:{{camel.sftp.hostcert.test-port}}/sftp?password=admin&strictHostKeyChecking=yes&useUserKnownHostsFile=false&knownHostsFile=";
+                        + knownHostsFile
+                        + 
"&caSignatureAlgorithms=ssh-ed25519,rsa-sha2-512,rsa-sha2-256&delete=true&fileName="
+                        + fileName,
+                TIMEOUT_MS,
+                String.class);
+        return Response.noContent().build();
+    }
+
+    /**
+     * Creates a known_hosts file with @cert-authority entry for the host CA.
+     * This allows the client to verify the server's host certificate.
+     */
+    private String createHostCaKnownHostsFile() throws Exception {
+        String resourcePath = "certs/host-ca.pub";
+        ClassLoader classLoader = 
Thread.currentThread().getContextClassLoader();
+
+        try (InputStream stream = 
classLoader.getResourceAsStream(resourcePath)) {
+            if (stream == null) {
+                throw new RuntimeException("Failed to load host CA public key 
from: " + resourcePath);
+            }
+            return processHostCaStream(stream);
+        }
+    }
+
+    private String processHostCaStream(InputStream hostCaStream) throws 
Exception {
+        String hostCaPubKey = new String(hostCaStream.readAllBytes()).trim();
+        String port = 
context.resolvePropertyPlaceholders("{{camel.sftp.hostcert.test-port}}");
+
+        // Create known_hosts with @cert-authority entry
+        String knownHostsContent = String.format("@cert-authority 
[localhost]:%s %s%n", port, hostCaPubKey);
+
+        // Use temp directory instead of "target" which may not exist in 
native mode runtime
+        java.nio.file.Path knownHostsPath = 
java.nio.file.Files.createTempFile("known_hosts_hostcert", ".txt");
+        java.nio.file.Files.writeString(knownHostsPath, knownHostsContent);
+
+        return knownHostsPath.toAbsolutePath().toString();
+    }
 }
diff --git a/integration-tests/ftp/src/main/resources/application.properties 
b/integration-tests/ftp/src/main/resources/application.properties
index 9d05789d61..25bfaf1cfa 100644
--- a/integration-tests/ftp/src/main/resources/application.properties
+++ b/integration-tests/ftp/src/main/resources/application.properties
@@ -18,4 +18,4 @@
 # Change to INFO level to get insights about commands run on the FTP server
 quarkus.log.category."org.apache.ftpserver".level = WARNING
 
-quarkus.native.resources.includes=certs/test-key-rsa.key,certs/test-key-rsa-cert.pub
+quarkus.native.resources.includes=certs/test-key-rsa.key,certs/test-key-rsa-cert.pub,certs/host-ca.pub,certs/host-key-rsa.key,certs/host-key-rsa-cert.pub
diff --git 
a/integration-tests/ftp/src/main/resources/certs/generate-certificates.sh 
b/integration-tests/ftp/src/main/resources/certs/generate-certificates.sh
index 8780f21483..8e9079b3e7 100755
--- a/integration-tests/ftp/src/main/resources/certs/generate-certificates.sh
+++ b/integration-tests/ftp/src/main/resources/certs/generate-certificates.sh
@@ -20,11 +20,17 @@
 # Script to generate OpenSSH certificate files for SFTP integration tests
 #
 # This script creates:
+# USER CERTIFICATES:
 # - test-key-rsa.key: RSA private key (2048 bits)
-# - test-key-rsa-cert.pub: OpenSSH certificate signed by a temporary CA
+# - test-key-rsa-cert.pub: OpenSSH user certificate signed by user CA
 #
-# The certificate is valid for 52 weeks and can be used for testing
-# certificate-based authentication with the mina-sftp component.
+# HOST CERTIFICATES:
+# - host-ca.pub: Host CA public key (for @cert-authority in known_hosts)
+# - host-key-rsa.key: RSA host private key (2048 bits)
+# - host-key-rsa-cert.pub: OpenSSH host certificate signed by host CA
+#
+# The certificates are valid for 52 weeks and can be used for testing
+# certificate-based authentication with the FTP component.
 #
 
 set -e
@@ -33,34 +39,66 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
 cd "$SCRIPT_DIR"
 
 echo "==================================================================="
-echo "Generating OpenSSH Certificates for MINA SFTP Integration Tests"
+echo "Generating OpenSSH Certificates for FTP Integration Tests"
 echo "==================================================================="
 echo ""
 
 echo "Cleaning up existing files..."
-rm -f ca-key ca-key.pub test-key-rsa.key test-key-rsa.key.pub 
test-key-rsa-cert.pub
+rm -f user-ca user-ca.pub test-key-rsa.key test-key-rsa.key.pub 
test-key-rsa-cert.pub
+rm -f host-ca host-ca.pub host-key-rsa.key host-key-rsa.key.pub 
host-key-rsa-cert.pub
 echo "Cleaned up existing files"
 
-echo "Generating temporary CA key pair..."
-ssh-keygen -t rsa -b 2048 -f ca-key -N "" -C "test-ca" > /dev/null 2>&1
-echo "Created ca-key and ca-key.pub"
+echo ""
+echo "--- USER CERTIFICATE GENERATION ---"
+echo ""
+
+echo "Generating user CA key pair..."
+ssh-keygen -t rsa -b 2048 -f user-ca -N "" -C "user-ca" > /dev/null 2>&1
+echo "Created user-ca and user-ca.pub"
 
 echo "Generating user RSA key pair..."
 ssh-keygen -t rsa -b 2048 -f test-key-rsa.key -N "" -C "test-rsa@test" > 
/dev/null 2>&1
 echo "Created test-key-rsa.key and test-key-rsa.key.pub"
 
-echo "Signing public key with CA to create certificate..."
-ssh-keygen -s ca-key \
+echo "Signing user public key with user CA to create certificate..."
+ssh-keygen -s user-ca \
   -I "test-user" \
-  -n testuser \
+  -n admin \
   -V +520w \
   test-key-rsa.key.pub > /dev/null 2>&1
 echo "Created test-key-rsa.key-cert.pub"
 
-echo "Renaming certificate to test-key-rsa-cert.pub..."
+echo "Renaming user certificate to test-key-rsa-cert.pub..."
 mv test-key-rsa.key-cert.pub test-key-rsa-cert.pub
 echo "Renamed to test-key-rsa-cert.pub"
 
+echo ""
+echo "--- HOST CERTIFICATE GENERATION ---"
+echo ""
+
+echo "Generating host CA key pair..."
+ssh-keygen -t ed25519 -f host-ca -N "" -C "host-ca" > /dev/null 2>&1
+echo "Created host-ca and host-ca.pub"
+
+echo "Generating host RSA key pair..."
+ssh-keygen -t rsa -b 2048 -f host-key-rsa.key -N "" -C "sftp-server@localhost" 
> /dev/null 2>&1
+echo "Created host-key-rsa.key and host-key-rsa.key.pub"
+
+echo "Signing host public key with host CA to create host certificate..."
+ssh-keygen -s host-ca \
+  -I "sftp-server" \
+  -h \
+  -n localhost \
+  -V +520w \
+  host-key-rsa.key.pub > /dev/null 2>&1
+echo "Created host-key-rsa.key-cert.pub"
+
+echo "Renaming host certificate to host-key-rsa-cert.pub..."
+mv host-key-rsa.key-cert.pub host-key-rsa-cert.pub
+echo "Renamed to host-key-rsa-cert.pub"
+
+echo ""
 echo "Cleaning up temporary files..."
-rm -f ca-key ca-key.pub test-key-rsa.key.pub
-echo "Removed CA keys and public key"
+rm -f user-ca user-ca.pub test-key-rsa.key.pub
+rm -f host-ca host-key-rsa.key.pub
+echo "Removed CA private keys and public keys"
diff --git a/integration-tests/ftp/src/main/resources/certs/host-ca.pub 
b/integration-tests/ftp/src/main/resources/certs/host-ca.pub
new file mode 100644
index 0000000000..d0a10f97cf
--- /dev/null
+++ b/integration-tests/ftp/src/main/resources/certs/host-ca.pub
@@ -0,0 +1 @@
+ssh-ed25519 
AAAAC3NzaC1lZDI1NTE5AAAAIITv5DGdGNCNkU+DMJsMsAsFoufh4yO5DB2PK48eUmqq host-ca
diff --git 
a/integration-tests/ftp/src/main/resources/certs/host-key-rsa-cert.pub 
b/integration-tests/ftp/src/main/resources/certs/host-key-rsa-cert.pub
new file mode 100644
index 0000000000..79c92a7e12
--- /dev/null
+++ b/integration-tests/ftp/src/main/resources/certs/host-key-rsa-cert.pub
@@ -0,0 +1 @@
[email protected] 
AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgqfpKfP1HcEq0OkSV20BryP+RpxsjCw3QYoLiO7G8p7sAAAADAQABAAABAQCktIEA/teg39lFRRPsFNVfbE93LCj7cewNUjZX+xoHWpBWA6FfaM1xBFmx99W0SAq9TwX8RC8yNzZAYOY4HQIwJYP9NNskMXrV4efQ/HFxg/OGETKDLi/bFgGEJPzIUX+vwLw+RVBcH8HhxHbhvCX/TBliZ6StOlIgoYi/2RKKp9uh3EmOU5gHozNz0jdzRPgVVQvgQvrW7E+2PS/GI67IUxElZSaI8qYFslXbw+iyQSdBg+ZqFl8Z9HVQweV/H5w0o1+87lWkaSIQxJccbmTcaub4Q+KWLci4qALE7yKLnVpuPJxe7zNV/uqd7fh85v5pl8MxQasZLduPf2AyoM1rAAAAAAAAAAAAAAA
 [...]
diff --git a/integration-tests/ftp/src/main/resources/certs/host-key-rsa.key 
b/integration-tests/ftp/src/main/resources/certs/host-key-rsa.key
new file mode 100644
index 0000000000..a8cff6531f
--- /dev/null
+++ b/integration-tests/ftp/src/main/resources/certs/host-key-rsa.key
@@ -0,0 +1,27 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
+NhAAAAAwEAAQAAAQEApLSBAP7XoN/ZRUUT7BTVX2xPdywo+3HsDVI2V/saB1qQVgOhX2jN
+cQRZsffVtEgKvU8F/EQvMjc2QGDmOB0CMCWD/TTbJDF61eHn0PxxcYPzhhEygy4v2xYBhC
+T8yFF/r8C8PkVQXB/B4cR24bwl/0wZYmekrTpSIKGIv9kSiqfbodxJjlOYB6Mzc9I3c0T4
+FVUL4EL61uxPtj0vxiOuyFMRJWUmiPKmBbJV28PoskEnQYPmahZfGfR1UMHlfx+cNKNfvO
+5VpGkiEMSXHG5k3Grm+EPili3IuKgCxO8ii51abjycXu8zVf7qne34fOb+aZfDMUGrGS3b
+j39gMqDNawAAA9CCNbkKgjW5CgAAAAdzc2gtcnNhAAABAQCktIEA/teg39lFRRPsFNVfbE
+93LCj7cewNUjZX+xoHWpBWA6FfaM1xBFmx99W0SAq9TwX8RC8yNzZAYOY4HQIwJYP9NNsk
+MXrV4efQ/HFxg/OGETKDLi/bFgGEJPzIUX+vwLw+RVBcH8HhxHbhvCX/TBliZ6StOlIgoY
+i/2RKKp9uh3EmOU5gHozNz0jdzRPgVVQvgQvrW7E+2PS/GI67IUxElZSaI8qYFslXbw+iy
+QSdBg+ZqFl8Z9HVQweV/H5w0o1+87lWkaSIQxJccbmTcaub4Q+KWLci4qALE7yKLnVpuPJ
+xe7zNV/uqd7fh85v5pl8MxQasZLduPf2AyoM1rAAAAAwEAAQAAAQBERCqKGpaOL+nSm7iP
+q+zqga6IMw4DdisENHSgz8twi9lyRUvwCzTHqKlyqcnyUL/eyi+taSd0tUyvr1oMnP1ork
+wAOZWw8S88Ekeup8tvZOUdRuh8VbrxIDRdrKT3dEwrsQN0/e66WFFYfcFWe9D1+Xk1/8ZS
+JG+g5cMT3WmhfRpBmIRZT3nHQTdjkrVIsK1dkbgCbxQBX/hKD/nV0AC/HjBbqx7MVvpK4N
+MKy+Prg/JUvy51GtUeQNZw92Gc7osLpFAzh2apgMhK1ZbWyPjrb/mQ/NXVG6ETuW+3ktwh
+qLLGPjwG/eE+UgWqn1LFgHINpD5y8NbuQ7bCkM5ADaF9AAAAgCIkD2uKemGJpnbEHBGVOO
+sRoP5TGDMPwueagpH8JPll6GfQo7NzxZQJttp4FDCmzbbTN6u7Jk7f8UHprhhzk//Lgm+a
+Ds1qGN11WA32MFCUJixtgc3re1W4nGF3BIshv4tScQVpMcBhDBtSJSzeVpHfeB+k2hzkK2
+/TCbMAHjmZAAAAgQDPbPrfiAbSjmCOjgf/aa82D73Rry/wL4d6bZTi2wwxu3HmzuA0G7L8
+qGV9UIEJ5jFHbQq/wP46XpiIESfkg+PmrUGOwZQ22cjpsPzxJzysvK3oYiuXduE8uz+c/F
+HDx1ONNeDB011k3h1JRcquYrU5SMqWnZLF/vnyvqQgywLXNwAAAIEAy0Z0WJFIiMYJTf4N
+Wa79DbsDutVei72QpoAwMlzBouD2YBArxznCsVC3rVKPVBlUTT2oszCfwQLo3fMjZs3yjW
+SrKc2/EDex8drZg+w262mX+bDQZD+PI1LgrpF7L5e5//id4On5ie6cwIc+8RJRelqhrftT
+T0lFiZ4C2JhdrW0AAAAVc2Z0cC1zZXJ2ZXJAbG9jYWxob3N0AQIDBAUG
+-----END OPENSSH PRIVATE KEY-----
diff --git 
a/integration-tests/ftp/src/main/resources/certs/test-key-rsa-cert.pub 
b/integration-tests/ftp/src/main/resources/certs/test-key-rsa-cert.pub
index ba21c6c28b..fa138337ce 100644
--- a/integration-tests/ftp/src/main/resources/certs/test-key-rsa-cert.pub
+++ b/integration-tests/ftp/src/main/resources/certs/test-key-rsa-cert.pub
@@ -1 +1 @@
[email protected] 
AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgwsB0wUJYWF7WQayMI3EFz63+rzdGxxmy6QmkXXigkbcAAAADAQABAAABAQCd2V7v8ELetZfmObUn3zP28B44AhcDnOdZHErgl1fe6e2Jmnja4BhdtZAG+XZEmKwlQnWNkRJfDs1/ryfP8xthcZIlklEb/6F2D2zmot5BnY6zzL6XWPtuTny1Ym7iah6KSPv9vS9nc2wcEA9BFu+CYHHWJYskv/PE/hwebae/upKafppCWJ97+Kdkc87Whsd1y2PxhhPPCbH/lOOOmzw2qTyxpYciHsr9NaBfoHRwvTWBdWjk6pYKtw+4gmWOmyAngOh9jcXeJ5pKUhWeJh5fmMrHL/mv/0DtrGQ2fhhrYZjIbkuha5EOFqurnXHjwwBz3Ey8JOhaF9UwQlCvOOWnAAAAAAAAAAAAAAA
 [...]
[email protected] 
AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgWeZP/HKtZqoYUuTZBJDuYgLpWoFI881IQ2mL7gMIVrIAAAADAQABAAABAQCQ6auYkjIBrtHexpzxGkfWoDU0IeRiye2HjGKZa7fHRdYYaQBstJXcnPgzcgOY70dzYe5A9WorWhi+33YWrox6k16WeeYREcogRZ12M0hnEZQa74J5yUHDxHGofHrgh4SIPqE/HOukC8X5LGYV5VPD4wabFdBxbpuPLuPcddWMhZCdd9OqXGizk5nwLhIOM7N3A5kDxn2NtyBPt3WsxCM8Y4d+yWR6BeoUzhBDRFx2yw1aNLbj7aoc7sMPOJXgIJDI0nm1mcdmF1FQqnPlG4zmh9G1B7B8cZfQ8kz+Q+GrFGkgPSwRqZ14+CUfymutuJzcU7hBDdfgbBu5UWnade7dAAAAAAAAAAAAAAA
 [...]
diff --git a/integration-tests/ftp/src/main/resources/certs/test-key-rsa.key 
b/integration-tests/ftp/src/main/resources/certs/test-key-rsa.key
index 751cc308be..ac6440d774 100644
--- a/integration-tests/ftp/src/main/resources/certs/test-key-rsa.key
+++ b/integration-tests/ftp/src/main/resources/certs/test-key-rsa.key
@@ -1,27 +1,27 @@
 -----BEGIN OPENSSH PRIVATE KEY-----
 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
-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
+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
 -----END OPENSSH PRIVATE KEY-----
diff --git 
a/extensions/ftp/deployment/src/main/java/org/apache/camel/quarkus/component/ftp/deployment/FtpProcessor.java
 
b/integration-tests/ftp/src/test/java/org/apache/camel/quarkus/component/sftp/it/SftpHostCertIT.java
similarity index 69%
copy from 
extensions/ftp/deployment/src/main/java/org/apache/camel/quarkus/component/ftp/deployment/FtpProcessor.java
copy to 
integration-tests/ftp/src/test/java/org/apache/camel/quarkus/component/sftp/it/SftpHostCertIT.java
index 218c96e6f6..2562a13d33 100644
--- 
a/extensions/ftp/deployment/src/main/java/org/apache/camel/quarkus/component/ftp/deployment/FtpProcessor.java
+++ 
b/integration-tests/ftp/src/test/java/org/apache/camel/quarkus/component/sftp/it/SftpHostCertIT.java
@@ -14,17 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.quarkus.component.ftp.deployment;
+package org.apache.camel.quarkus.component.sftp.it;
 
-import io.quarkus.deployment.annotations.BuildStep;
-import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.quarkus.test.junit.QuarkusIntegrationTest;
 
-class FtpProcessor {
-
-    private static final String FEATURE = "camel-ftp";
-
-    @BuildStep
-    FeatureBuildItem feature() {
-        return new FeatureBuildItem(FEATURE);
-    }
+/**
+ * Integration tests for SFTP host certificate verification in native mode.
+ */
+@QuarkusIntegrationTest
+class SftpHostCertIT extends SftpHostCertTest {
 }
diff --git 
a/integration-tests/ftp/src/test/java/org/apache/camel/quarkus/component/sftp/it/SftpHostCertTest.java
 
b/integration-tests/ftp/src/test/java/org/apache/camel/quarkus/component/sftp/it/SftpHostCertTest.java
new file mode 100644
index 0000000000..d60935976f
--- /dev/null
+++ 
b/integration-tests/ftp/src/test/java/org/apache/camel/quarkus/component/sftp/it/SftpHostCertTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.component.sftp.it;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import io.restassured.http.ContentType;
+import io.smallrye.certs.Format;
+import io.smallrye.certs.junit5.Certificate;
+import org.apache.camel.quarkus.test.support.certificate.TestCertificates;
+import org.apache.camel.quarkus.test.support.sftp.SftpHostCertTestResource;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+
+@TestCertificates(certificates = {
+        @Certificate(name = "ftp", formats = {
+                Format.PEM }, password = "password"),
+        @Certificate(name = "ftp", formats = {
+                Format.PKCS12 }, password = "password") })
+@QuarkusTest
+@QuarkusTestResource(SftpHostCertTestResource.class)
+class SftpHostCertTest {
+
+    @Test
+    public void testHostCertificateVerification() {
+        RestAssured.given()
+                .contentType(ContentType.TEXT)
+                .body("Host certificate verification test")
+                .post("/sftp/hostcert/create/hostcert-test.txt")
+                .then()
+                .statusCode(201);
+
+        RestAssured.get("/sftp/hostcert/get/hostcert-test.txt")
+                .then()
+                .statusCode(200)
+                .body(is("Host certificate verification test"));
+
+        RestAssured.delete("/sftp/hostcert/delete/hostcert-test.txt")
+                .then()
+                .statusCode(204);
+    }
+
+    @Test
+    public void testHostCertificateVerificationWithCaSignatureAlgorithms() {
+        // Test host certificate verification with specific CA signature 
algorithms
+        RestAssured.given()
+                .contentType(ContentType.TEXT)
+                .body("Host cert with CA algorithms test")
+                
.post("/sftp/hostcertWithAlgorithms/create/hostcert-algo-test.txt")
+                .then()
+                .statusCode(201);
+
+        
RestAssured.get("/sftp/hostcertWithAlgorithms/get/hostcert-algo-test.txt")
+                .then()
+                .statusCode(200)
+                .body(is("Host cert with CA algorithms test"));
+
+        
RestAssured.delete("/sftp/hostcertWithAlgorithms/delete/hostcert-algo-test.txt")
+                .then()
+                .statusCode(204);
+    }
+}


Reply via email to