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

davidzollo pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/seatunnel.git


The following commit(s) were added to refs/heads/dev by this push:
     new 32f4ed3808 [Fix][Connector-V2] Support SFTP keyfile option (#11078)
32f4ed3808 is described below

commit 32f4ed380898e009b6725035894a9c596ebc850e
Author: Jast <[email protected]>
AuthorDate: Sat Jun 13 19:38:01 2026 +0800

    [Fix][Connector-V2] Support SFTP keyfile option (#11078)
---
 docs/en/connectors/sink/SftpFile.md                |  9 ++++--
 docs/en/connectors/source/SftpFile.md              |  3 +-
 docs/zh/connectors/sink/SftpFile.md                | 11 ++++++--
 docs/zh/connectors/source/SftpFile.md              |  3 +-
 .../seatunnel/file/sftp/config/SftpConf.java       | 15 +++++++---
 .../file/sftp/config/SftpFileBaseOptions.java      |  5 ++++
 .../file/sftp/sink/SftpFileSinkFactory.java        |  3 +-
 .../file/sftp/source/SftpFileSourceFactory.java    |  1 +
 .../seatunnel/file/sftp/SftpFileFactoryTest.java   | 32 +++++++++++++++++++++-
 9 files changed, 69 insertions(+), 13 deletions(-)

diff --git a/docs/en/connectors/sink/SftpFile.md 
b/docs/en/connectors/sink/SftpFile.md
index 683918c299..4d6a0592a1 100644
--- a/docs/en/connectors/sink/SftpFile.md
+++ b/docs/en/connectors/sink/SftpFile.md
@@ -46,7 +46,8 @@ If you use SeaTunnel Engine, It automatically integrated the 
hadoop jar when you
 | host                                  | string  | yes      | -               
                           |                                                    
                                                                                
                                             |
 | port                                  | int     | yes      | -               
                           |                                                    
                                                                                
                                             |
 | user                                  | string  | yes      | -               
                           |                                                    
                                                                                
                                             |
-| password                              | string  | yes      | -               
                           |                                                    
                                                                                
                                             |
+| password                              | string  | no       | -               
                           | Required when `keyfile` is not set.                
                                                                                
                                             |
+| keyfile                               | string  | no       | -               
                           | Private key file path used for SFTP public key 
authentication.                                                                 
                                                  |
 | path                                  | string  | yes      | -               
                           |                                                    
                                                                                
                                             |
 | tmp_path                              | string  | yes      | /tmp/seatunnel  
                           | The result file will write to a tmp path first and 
then use `mv` to submit tmp dir to target dir. Need a FTP dir.                  
                                             |
 | custom_filename                       | boolean | no       | false           
                           | Whether you need custom the filename               
                                                                                
                                             |
@@ -97,7 +98,11 @@ The target sftp user is required
 
 ### password [string]
 
-The target sftp password is required
+The target sftp password. Required when `keyfile` is not set.
+
+### keyfile [string]
+
+The private key file path used for SFTP public key authentication.
 
 ### path [string]
 
diff --git a/docs/en/connectors/source/SftpFile.md 
b/docs/en/connectors/source/SftpFile.md
index f32adda510..3e95521f07 100644
--- a/docs/en/connectors/source/SftpFile.md
+++ b/docs/en/connectors/source/SftpFile.md
@@ -83,7 +83,8 @@ The File does not have a specific type list, and we can 
indicate which SeaTunnel
 | host                       | String  | Yes      | -                          
   | The target sftp host is required                                           
                                                                                
                                                                                
                                                                                
                                                     |
 | port                       | Int     | Yes      | -                          
   | The target sftp port is required                                           
                                                                                
                                                                                
                                                                                
                                                     |
 | user                       | String  | Yes      | -                          
   | The target sftp username is required                                       
                                                                                
                                                                                
                                                                                
                                                     |
-| password                   | String  | Yes      | -                          
   | The target sftp password is required                                       
                                                                                
                                                                                
                                                                                
                                                     |
+| password                   | String  | No       | -                          
   | The target sftp password. Required when `keyfile` is not set.              
                                                                                
                                                                                
                                                                                
                                                     |
+| keyfile                    | String  | No       | -                          
   | The private key file path used for SFTP public key authentication.         
                                                                                
                                                                                
                                                                                
                                                     |
 | path                       | String  | Yes      | -                          
   | The source file path.                                                      
                                                                                
                                                                                
                                                                                
                                                     |
 | file_format_type           | String  | Yes      | -                          
   | Please check #file_format_type below                                       
                                                                                
                                                                                
                                                                                
                                                     |
 | file_filter_pattern        | String  | No       | -                          
   | Filter pattern, which used for filtering files.                            
                                                                                
                                                                                
                                                                                
                                                     |
diff --git a/docs/zh/connectors/sink/SftpFile.md 
b/docs/zh/connectors/sink/SftpFile.md
index 7a4c791fdf..884e5356fe 100644
--- a/docs/zh/connectors/sink/SftpFile.md
+++ b/docs/zh/connectors/sink/SftpFile.md
@@ -45,7 +45,8 @@ import ChangeLog from '../changelog/connector-file-sftp.md';
 | host                                  | string  | 是    | -                   
                       |                                                        
   |
 | port                                  | int     | 是    | -                   
                       |                                                        
   |
 | user                                  | string  | 是    | -                   
                       |                                                        
   |
-| password                              | string  | 是    | -                   
                       |                                                        
   |
+| password                              | string  | 否    | -                   
                       | 未配置 `keyfile` 时需要配置。                                   
   |
+| keyfile                               | string  | 否    | -                   
                       | 用于 SFTP 公钥认证的私钥文件路径。                                   
 |
 | path                                  | string  | 是    | -                   
                       |                                                        
   |
 | tmp_path                              | string  | 是    | /tmp/seatunnel      
                       | 结果文件将首先写入临时路径,然后使用`mv`将临时目录剪切到目标目录。需要一个FTP目录。          
   |
 | custom_filename                       | boolean | 否    | false               
                       | 是否需要自定义文件名                                             
   |
@@ -94,7 +95,11 @@ import ChangeLog from '../changelog/connector-file-sftp.md';
 
 ### password [string]
 
-目标sftp密码,必填。
+目标sftp密码。未配置 `keyfile` 时需要配置。
+
+### keyfile [string]
+
+用于 SFTP 公钥认证的私钥文件路径。
 
 ### path [string]
 
@@ -359,4 +364,4 @@ LocalFile {
 
 ## 变更日志
 
-<ChangeLog />
\ No newline at end of file
+<ChangeLog />
diff --git a/docs/zh/connectors/source/SftpFile.md 
b/docs/zh/connectors/source/SftpFile.md
index c225af5a58..ce71dd1cb5 100644
--- a/docs/zh/connectors/source/SftpFile.md
+++ b/docs/zh/connectors/source/SftpFile.md
@@ -83,7 +83,8 @@ import ChangeLog from '../changelog/connector-file-sftp.md';
 | host                       | String  | 是    | -                   | 
目标sftp主机是必需的                                                                    
                                                                                
                                                                                
   |
 | port                       | Int     | 是    | -                   | 
目标sftp端口是必需的                                                                    
                                                                                
                                                                                
   |
 | user                       | String  | 是    | -                   | 
目标sftp用户名是必需的                                                                   
                                                                                
                                                                                
   |
-| password                   | String  | 是    | -                   | 
目标sftp密码是必需的                                                                    
                                                                                
                                                                                
   |
+| password                   | String  | 否    | -                   | 
目标sftp密码。未配置 `keyfile` 时需要配置。                                                   
                                                                                
                                                                                
      |
+| keyfile                    | String  | 否    | -                   | 用于 SFTP 
公钥认证的私钥文件路径。                                                                    
                                                                                
                                                                          |
 | path                       | String  | 是    | -                   | 源文件路径。   
                                                                                
                                                                                
                                                                          |
 | file_format_type           | String  | 是    | -                   | 
请查看下面的#file_format_type                                                         
                                                                                
                                                                                
   |
 | file_filter_pattern        | String  | 否    | -                   | 
过滤模式,用于过滤文件。                                                                    
                                                                                
                                                                                
   |
diff --git 
a/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/config/SftpConf.java
 
b/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/config/SftpConf.java
index 2849b5b7fa..75d0e3e3f0 100644
--- 
a/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/config/SftpConf.java
+++ 
b/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/config/SftpConf.java
@@ -19,6 +19,7 @@ package 
org.apache.seatunnel.connectors.seatunnel.file.sftp.config;
 
 import org.apache.seatunnel.api.configuration.ReadonlyConfig;
 import org.apache.seatunnel.connectors.seatunnel.file.config.HadoopConf;
+import 
org.apache.seatunnel.connectors.seatunnel.file.sftp.system.SFTPFileSystem;
 
 import java.util.HashMap;
 
@@ -47,10 +48,16 @@ public class SftpConf extends HadoopConf {
         String defaultFS = String.format("sftp://%s:%s";, host, port);
         HadoopConf hadoopConf = new SftpConf(defaultFS);
         HashMap<String, String> sftpOptions = new HashMap<>();
-        sftpOptions.put("fs.sftp.user." + host, 
config.get(SftpFileBaseOptions.SFTP_USER));
-        sftpOptions.put(
-                "fs.sftp.password." + host + "." + 
config.get(SftpFileBaseOptions.SFTP_USER),
-                config.get(SftpFileBaseOptions.SFTP_PASSWORD));
+        String user = config.get(SftpFileBaseOptions.SFTP_USER);
+        sftpOptions.put(SFTPFileSystem.FS_SFTP_USER_PREFIX + host, user);
+        config.getOptional(SftpFileBaseOptions.SFTP_PASSWORD)
+                .ifPresent(
+                        password ->
+                                sftpOptions.put(
+                                        SFTPFileSystem.FS_SFTP_PASSWORD_PREFIX 
+ host + "." + user,
+                                        password));
+        config.getOptional(SftpFileBaseOptions.SFTP_KEYFILE)
+                .ifPresent(keyfile -> 
sftpOptions.put(SFTPFileSystem.FS_SFTP_KEYFILE, keyfile));
         hadoopConf.setExtraOptions(sftpOptions);
         return hadoopConf;
     }
diff --git 
a/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/config/SftpFileBaseOptions.java
 
b/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/config/SftpFileBaseOptions.java
index 5a614fbec7..75e435c3f7 100644
--- 
a/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/config/SftpFileBaseOptions.java
+++ 
b/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/config/SftpFileBaseOptions.java
@@ -27,6 +27,11 @@ public class SftpFileBaseOptions extends FileBaseOptions {
                     .stringType()
                     .noDefaultValue()
                     .withDescription("SFTP server password");
+    public static final Option<String> SFTP_KEYFILE =
+            Options.key("keyfile")
+                    .stringType()
+                    .noDefaultValue()
+                    .withDescription("SFTP private key file path");
     public static final Option<String> SFTP_USER =
             Options.key("user")
                     .stringType()
diff --git 
a/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/sink/SftpFileSinkFactory.java
 
b/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/sink/SftpFileSinkFactory.java
index eb68f31158..0bfe1196dd 100644
--- 
a/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/sink/SftpFileSinkFactory.java
+++ 
b/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/sink/SftpFileSinkFactory.java
@@ -52,7 +52,8 @@ public class SftpFileSinkFactory extends 
BaseMultipleTableFileSinkFactory {
                 .required(SftpFileSinkOptions.SFTP_HOST)
                 .required(SftpFileSinkOptions.SFTP_PORT)
                 .required(SftpFileSinkOptions.SFTP_USER)
-                .required(SftpFileSinkOptions.SFTP_PASSWORD)
+                .optional(SftpFileSinkOptions.SFTP_PASSWORD)
+                .optional(SftpFileSinkOptions.SFTP_KEYFILE)
                 .optional(FileBaseSinkOptions.FILE_FORMAT_TYPE)
                 .optional(FileBaseSinkOptions.SCHEMA_SAVE_MODE)
                 .optional(FileBaseSinkOptions.DATA_SAVE_MODE)
diff --git 
a/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/source/SftpFileSourceFactory.java
 
b/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/source/SftpFileSourceFactory.java
index 16e22ae664..4ce72d9eb4 100644
--- 
a/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/source/SftpFileSourceFactory.java
+++ 
b/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/source/SftpFileSourceFactory.java
@@ -51,6 +51,7 @@ public class SftpFileSourceFactory implements 
TableSourceFactory {
                 .optional(SftpFileSourceOptions.SFTP_PORT)
                 .optional(SftpFileSourceOptions.SFTP_USER)
                 .optional(SftpFileSourceOptions.SFTP_PASSWORD)
+                .optional(SftpFileSourceOptions.SFTP_KEYFILE)
                 .optional(FileBaseSourceOptions.FILE_FORMAT_TYPE)
                 .conditional(
                         FileBaseSourceOptions.FILE_FORMAT_TYPE,
diff --git 
a/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/test/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/SftpFileFactoryTest.java
 
b/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/test/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/SftpFileFactoryTest.java
index 9ed5942d18..b38f8c8794 100644
--- 
a/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/test/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/SftpFileFactoryTest.java
+++ 
b/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/test/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/SftpFileFactoryTest.java
@@ -17,17 +17,24 @@
 
 package org.apache.seatunnel.connectors.seatunnel.file.sftp;
 
+import org.apache.seatunnel.api.configuration.ReadonlyConfig;
 import org.apache.seatunnel.api.configuration.util.Expression;
 import org.apache.seatunnel.api.configuration.util.OptionRule;
 import org.apache.seatunnel.api.configuration.util.RequiredOption;
 import 
org.apache.seatunnel.connectors.seatunnel.file.config.FileBaseSourceOptions;
 import org.apache.seatunnel.connectors.seatunnel.file.config.FileSyncMode;
+import org.apache.seatunnel.connectors.seatunnel.file.config.HadoopConf;
+import org.apache.seatunnel.connectors.seatunnel.file.sftp.config.SftpConf;
 import 
org.apache.seatunnel.connectors.seatunnel.file.sftp.sink.SftpFileSinkFactory;
 import 
org.apache.seatunnel.connectors.seatunnel.file.sftp.source.SftpFileSourceFactory;
+import 
org.apache.seatunnel.connectors.seatunnel.file.sftp.system.SFTPFileSystem;
 
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
+import java.util.HashMap;
+import java.util.Map;
+
 class SftpFileFactoryTest {
 
     @Test
@@ -48,6 +55,9 @@ class SftpFileFactoryTest {
                 
optionRule.getOptionalOptions().contains(FileBaseSourceOptions.SCAN_INTERVAL));
         Assertions.assertTrue(
                 
optionRule.getOptionalOptions().contains(FileBaseSourceOptions.START_MODE));
+        Assertions.assertTrue(
+                optionRule.getOptionalOptions().stream()
+                        .anyMatch(option -> "keyfile".equals(option.key())));
 
         Expression expectExpression =
                 Expression.of(FileBaseSourceOptions.SYNC_MODE, 
FileSyncMode.UPDATE);
@@ -60,6 +70,26 @@ class SftpFileFactoryTest {
                                         required.getOptions()
                                                 
.contains(FileBaseSourceOptions.TARGET_PATH))
                         .anyMatch(required -> 
expectExpression.equals(required.getExpression())));
-        Assertions.assertNotNull((new SftpFileSinkFactory()).optionRule());
+        OptionRule sinkOptionRule = (new SftpFileSinkFactory()).optionRule();
+        Assertions.assertNotNull(sinkOptionRule);
+        Assertions.assertTrue(
+                sinkOptionRule.getOptionalOptions().stream()
+                        .anyMatch(option -> "keyfile".equals(option.key())));
+    }
+
+    @Test
+    void buildHadoopConfWithKeyfile() {
+        Map<String, Object> configMap = new HashMap<>();
+        configMap.put("host", "sftp.example.com");
+        configMap.put("port", 22);
+        configMap.put("user", "seatunnel");
+        configMap.put("password", "secret");
+        configMap.put("keyfile", "/home/seatunnel/.ssh/id_rsa");
+
+        HadoopConf hadoopConf = 
SftpConf.buildWithConfig(ReadonlyConfig.fromMap(configMap));
+
+        Assertions.assertEquals(
+                "/home/seatunnel/.ssh/id_rsa",
+                
hadoopConf.getExtraOptions().get(SFTPFileSystem.FS_SFTP_KEYFILE));
     }
 }

Reply via email to