From d78443cc06472ddb9a90a2d724c53e0b4bbd2d3f Mon Sep 17 00:00:00 2001 From: Rodrigo Cavalcanti Date: Wed, 6 Oct 2021 13:57:27 -0300 Subject: [PATCH 1/2] demo uplaud SFTP --- .../.gitignore | 0 .../.mvn/wrapper/maven-wrapper.jar | Bin .../.mvn/wrapper/maven-wrapper.properties | 0 {spring-sftp-upload-demo => sftp-upload-demo}/mvnw | 0 .../mvnw.cmd | 0 .../pom.xml | 0 .../src/main/java/com/sftp}/SftpConfig.java | 2 +- .../com/sftp}/SpringSftpUploadDemoApplication.java | 2 +- .../src/main/resources/application.properties | 0 .../src/test/java/com/sftp}/EmbeddedSftpServer.java | 7 +------ .../sftp}/SpringSftpUploadDemoApplicationTests.java | 4 ++-- .../src/test/resources/keys/sftp_rsa | 0 .../src/test/resources/keys/sftp_rsa.pub | 0 13 files changed, 5 insertions(+), 10 deletions(-) rename {spring-sftp-upload-demo => sftp-upload-demo}/.gitignore (100%) rename {spring-sftp-upload-demo => sftp-upload-demo}/.mvn/wrapper/maven-wrapper.jar (100%) rename {spring-sftp-upload-demo => sftp-upload-demo}/.mvn/wrapper/maven-wrapper.properties (100%) rename {spring-sftp-upload-demo => sftp-upload-demo}/mvnw (100%) rename {spring-sftp-upload-demo => sftp-upload-demo}/mvnw.cmd (100%) rename {spring-sftp-upload-demo => sftp-upload-demo}/pom.xml (100%) rename {spring-sftp-upload-demo/src/main/java/com/pavelsklenar => sftp-upload-demo/src/main/java/com/sftp}/SftpConfig.java (99%) rename {spring-sftp-upload-demo/src/main/java/com/pavelsklenar => sftp-upload-demo/src/main/java/com/sftp}/SpringSftpUploadDemoApplication.java (95%) rename {spring-sftp-upload-demo => sftp-upload-demo}/src/main/resources/application.properties (100%) rename {spring-sftp-upload-demo/src/test/java/com/pavelsklenar => sftp-upload-demo/src/test/java/com/sftp}/EmbeddedSftpServer.java (97%) rename {spring-sftp-upload-demo/src/test/java/com/pavelsklenar => sftp-upload-demo/src/test/java/com/sftp}/SpringSftpUploadDemoApplicationTests.java (96%) rename {spring-sftp-upload-demo => sftp-upload-demo}/src/test/resources/keys/sftp_rsa (100%) rename {spring-sftp-upload-demo => sftp-upload-demo}/src/test/resources/keys/sftp_rsa.pub (100%) diff --git a/spring-sftp-upload-demo/.gitignore b/sftp-upload-demo/.gitignore similarity index 100% rename from spring-sftp-upload-demo/.gitignore rename to sftp-upload-demo/.gitignore diff --git a/spring-sftp-upload-demo/.mvn/wrapper/maven-wrapper.jar b/sftp-upload-demo/.mvn/wrapper/maven-wrapper.jar similarity index 100% rename from spring-sftp-upload-demo/.mvn/wrapper/maven-wrapper.jar rename to sftp-upload-demo/.mvn/wrapper/maven-wrapper.jar diff --git a/spring-sftp-upload-demo/.mvn/wrapper/maven-wrapper.properties b/sftp-upload-demo/.mvn/wrapper/maven-wrapper.properties similarity index 100% rename from spring-sftp-upload-demo/.mvn/wrapper/maven-wrapper.properties rename to sftp-upload-demo/.mvn/wrapper/maven-wrapper.properties diff --git a/spring-sftp-upload-demo/mvnw b/sftp-upload-demo/mvnw similarity index 100% rename from spring-sftp-upload-demo/mvnw rename to sftp-upload-demo/mvnw diff --git a/spring-sftp-upload-demo/mvnw.cmd b/sftp-upload-demo/mvnw.cmd similarity index 100% rename from spring-sftp-upload-demo/mvnw.cmd rename to sftp-upload-demo/mvnw.cmd diff --git a/spring-sftp-upload-demo/pom.xml b/sftp-upload-demo/pom.xml similarity index 100% rename from spring-sftp-upload-demo/pom.xml rename to sftp-upload-demo/pom.xml diff --git a/spring-sftp-upload-demo/src/main/java/com/pavelsklenar/SftpConfig.java b/sftp-upload-demo/src/main/java/com/sftp/SftpConfig.java similarity index 99% rename from spring-sftp-upload-demo/src/main/java/com/pavelsklenar/SftpConfig.java rename to sftp-upload-demo/src/main/java/com/sftp/SftpConfig.java index 098e5a7..844f39e 100644 --- a/spring-sftp-upload-demo/src/main/java/com/pavelsklenar/SftpConfig.java +++ b/sftp-upload-demo/src/main/java/com/sftp/SftpConfig.java @@ -1,4 +1,4 @@ -package com.pavelsklenar; +package com.sftp; import java.io.File; diff --git a/spring-sftp-upload-demo/src/main/java/com/pavelsklenar/SpringSftpUploadDemoApplication.java b/sftp-upload-demo/src/main/java/com/sftp/SpringSftpUploadDemoApplication.java similarity index 95% rename from spring-sftp-upload-demo/src/main/java/com/pavelsklenar/SpringSftpUploadDemoApplication.java rename to sftp-upload-demo/src/main/java/com/sftp/SpringSftpUploadDemoApplication.java index 8bccdb0..ae46da5 100644 --- a/spring-sftp-upload-demo/src/main/java/com/pavelsklenar/SpringSftpUploadDemoApplication.java +++ b/sftp-upload-demo/src/main/java/com/sftp/SpringSftpUploadDemoApplication.java @@ -1,4 +1,4 @@ -package com.pavelsklenar; +package com.sftp; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/spring-sftp-upload-demo/src/main/resources/application.properties b/sftp-upload-demo/src/main/resources/application.properties similarity index 100% rename from spring-sftp-upload-demo/src/main/resources/application.properties rename to sftp-upload-demo/src/main/resources/application.properties diff --git a/spring-sftp-upload-demo/src/test/java/com/pavelsklenar/EmbeddedSftpServer.java b/sftp-upload-demo/src/test/java/com/sftp/EmbeddedSftpServer.java similarity index 97% rename from spring-sftp-upload-demo/src/test/java/com/pavelsklenar/EmbeddedSftpServer.java rename to sftp-upload-demo/src/test/java/com/sftp/EmbeddedSftpServer.java index 62544d6..4c6ad9d 100644 --- a/spring-sftp-upload-demo/src/test/java/com/pavelsklenar/EmbeddedSftpServer.java +++ b/sftp-upload-demo/src/test/java/com/sftp/EmbeddedSftpServer.java @@ -1,4 +1,4 @@ -package com.pavelsklenar; +package com.sftp; import java.io.IOException; import java.io.InputStream; @@ -27,11 +27,6 @@ import org.springframework.util.SocketUtils; import org.springframework.util.StreamUtils; -/** - * SFTP server for integration testing - * @author Artem Bilan - * @author pavel.sklenar - */ public class EmbeddedSftpServer implements InitializingBean, SmartLifecycle { public static final int PORT = SocketUtils.findAvailableTcpPort(); diff --git a/spring-sftp-upload-demo/src/test/java/com/pavelsklenar/SpringSftpUploadDemoApplicationTests.java b/sftp-upload-demo/src/test/java/com/sftp/SpringSftpUploadDemoApplicationTests.java similarity index 96% rename from spring-sftp-upload-demo/src/test/java/com/pavelsklenar/SpringSftpUploadDemoApplicationTests.java rename to sftp-upload-demo/src/test/java/com/sftp/SpringSftpUploadDemoApplicationTests.java index 549173b..008a344 100644 --- a/spring-sftp-upload-demo/src/test/java/com/pavelsklenar/SpringSftpUploadDemoApplicationTests.java +++ b/sftp-upload-demo/src/test/java/com/sftp/SpringSftpUploadDemoApplicationTests.java @@ -1,4 +1,4 @@ -package com.pavelsklenar; +package com.sftp; import static org.junit.Assert.assertEquals; @@ -20,7 +20,7 @@ import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; -import com.pavelsklenar.SftpConfig.UploadGateway; +import com.sftp.SftpConfig.UploadGateway; @RunWith(SpringRunner.class) @SpringBootTest diff --git a/spring-sftp-upload-demo/src/test/resources/keys/sftp_rsa b/sftp-upload-demo/src/test/resources/keys/sftp_rsa similarity index 100% rename from spring-sftp-upload-demo/src/test/resources/keys/sftp_rsa rename to sftp-upload-demo/src/test/resources/keys/sftp_rsa diff --git a/spring-sftp-upload-demo/src/test/resources/keys/sftp_rsa.pub b/sftp-upload-demo/src/test/resources/keys/sftp_rsa.pub similarity index 100% rename from spring-sftp-upload-demo/src/test/resources/keys/sftp_rsa.pub rename to sftp-upload-demo/src/test/resources/keys/sftp_rsa.pub From e6d855063dfe7a5948a475e6c6d2cb690c30660b Mon Sep 17 00:00:00 2001 From: Rodrigo Cavalcanti Date: Mon, 1 Nov 2021 18:37:37 -0300 Subject: [PATCH 2/2] rezipar --- sftp-upload-demo/sftp-upload-demo.zip | Bin 0 -> 32741 bytes .../src/main/java/com/sftp/SftpConfig.java | 91 ----------- .../sftp/SpringSftpUploadDemoApplication.java | 16 -- .../java/com/sftp/EmbeddedSftpServer.java | 144 ------------------ .../SpringSftpUploadDemoApplicationTests.java | 80 ---------- 5 files changed, 331 deletions(-) create mode 100644 sftp-upload-demo/sftp-upload-demo.zip delete mode 100644 sftp-upload-demo/src/main/java/com/sftp/SftpConfig.java delete mode 100644 sftp-upload-demo/src/main/java/com/sftp/SpringSftpUploadDemoApplication.java delete mode 100644 sftp-upload-demo/src/test/java/com/sftp/EmbeddedSftpServer.java delete mode 100644 sftp-upload-demo/src/test/java/com/sftp/SpringSftpUploadDemoApplicationTests.java diff --git a/sftp-upload-demo/sftp-upload-demo.zip b/sftp-upload-demo/sftp-upload-demo.zip new file mode 100644 index 0000000000000000000000000000000000000000..5e149ee154da07327b861b84ebe45bb412f4b242 GIT binary patch literal 32741 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˭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 literal 0 HcmV?d00001 diff --git a/sftp-upload-demo/src/main/java/com/sftp/SftpConfig.java b/sftp-upload-demo/src/main/java/com/sftp/SftpConfig.java deleted file mode 100644 index 844f39e..0000000 --- a/sftp-upload-demo/src/main/java/com/sftp/SftpConfig.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.sftp; - -import java.io.File; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.io.Resource; -import org.springframework.expression.common.LiteralExpression; -import org.springframework.integration.annotation.Gateway; -import org.springframework.integration.annotation.MessagingGateway; -import org.springframework.integration.annotation.ServiceActivator; -import org.springframework.integration.file.FileNameGenerator; -import org.springframework.integration.file.remote.session.CachingSessionFactory; -import org.springframework.integration.file.remote.session.SessionFactory; -import org.springframework.integration.sftp.outbound.SftpMessageHandler; -import org.springframework.integration.sftp.session.DefaultSftpSessionFactory; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHandler; - -import com.jcraft.jsch.ChannelSftp.LsEntry; - -@Configuration -public class SftpConfig { - - @Value("${sftp.host}") - private String sftpHost; - - @Value("${sftp.port:22}") - private int sftpPort; - - @Value("${sftp.user}") - private String sftpUser; - - @Value("${sftp.privateKey:#{null}}") - private Resource sftpPrivateKey; - - @Value("${sftp.privateKeyPassphrase:}") - private String sftpPrivateKeyPassphrase; - - @Value("${sftp.password:#{null}}") - private String sftpPasword; - - @Value("${sftp.remote.directory:/}") - private String sftpRemoteDirectory; - - @Bean - public SessionFactory sftpSessionFactory() { - DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true); - factory.setHost(sftpHost); - factory.setPort(sftpPort); - factory.setUser(sftpUser); - if (sftpPrivateKey != null) { - factory.setPrivateKey(sftpPrivateKey); - factory.setPrivateKeyPassphrase(sftpPrivateKeyPassphrase); - } else { - factory.setPassword(sftpPasword); - } - factory.setAllowUnknownKeys(true); - return new CachingSessionFactory(factory); - } - - @Bean - @ServiceActivator(inputChannel = "toSftpChannel") - public MessageHandler handler() { - SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory()); - handler.setRemoteDirectoryExpression(new LiteralExpression(sftpRemoteDirectory)); - handler.setFileNameGenerator(new FileNameGenerator() { - - @Override - public String generateFileName(Message message) { - if (message.getPayload() instanceof File) { - return ((File) message.getPayload()).getName(); - } else { - throw new IllegalArgumentException("File expected as payload."); - } - } - - }); - return handler; - } - - @MessagingGateway - public interface UploadGateway { - - @Gateway(requestChannel = "toSftpChannel") - void upload(File file); - - } - -} diff --git a/sftp-upload-demo/src/main/java/com/sftp/SpringSftpUploadDemoApplication.java b/sftp-upload-demo/src/main/java/com/sftp/SpringSftpUploadDemoApplication.java deleted file mode 100644 index ae46da5..0000000 --- a/sftp-upload-demo/src/main/java/com/sftp/SpringSftpUploadDemoApplication.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.sftp; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.integration.annotation.IntegrationComponentScan; -import org.springframework.integration.config.EnableIntegration; - -@SpringBootApplication -@IntegrationComponentScan -@EnableIntegration -public class SpringSftpUploadDemoApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringSftpUploadDemoApplication.class, args); - } -} diff --git a/sftp-upload-demo/src/test/java/com/sftp/EmbeddedSftpServer.java b/sftp-upload-demo/src/test/java/com/sftp/EmbeddedSftpServer.java deleted file mode 100644 index 4c6ad9d..0000000 --- a/sftp-upload-demo/src/test/java/com/sftp/EmbeddedSftpServer.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.sftp; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.KeyFactory; -import java.security.PublicKey; -import java.security.spec.RSAPublicKeySpec; -import java.util.Collections; - -import org.apache.commons.codec.binary.Base64; -import org.apache.sshd.common.NamedFactory; -import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory; -import org.apache.sshd.server.Command; -import org.apache.sshd.server.SshServer; -import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator; -import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider; -import org.apache.sshd.server.scp.ScpCommandFactory; -import org.apache.sshd.server.session.ServerSession; -import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.SmartLifecycle; -import org.springframework.core.io.ClassPathResource; -import org.springframework.util.SocketUtils; -import org.springframework.util.StreamUtils; - -public class EmbeddedSftpServer implements InitializingBean, SmartLifecycle { - - public static final int PORT = SocketUtils.findAvailableTcpPort(); - - private final SshServer server = SshServer.setUpDefaultServer(); - - private volatile int port; - - private volatile boolean running; - - public void setPort(int port) { - this.port = port; - } - - @Override - public void afterPropertiesSet() throws Exception { - final PublicKey allowedKey = decodePublicKey(); - this.server.setPublickeyAuthenticator(new PublickeyAuthenticator() { - - @Override - public boolean authenticate(String username, PublicKey key, ServerSession session) { - return key.equals(allowedKey); - } - - }); - this.server.setPort(this.port); - this.server.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(Files.createTempFile("host_file", ".ser"))); - this.server.setSubsystemFactories(Collections.>singletonList(new SftpSubsystemFactory())); - server.setFileSystemFactory(new VirtualFileSystemFactory(Files.createTempDirectory("SFTP_TEMP"))); - server.setCommandFactory(new ScpCommandFactory()); - } - - public void setHomeFolder(Path path) { - server.setFileSystemFactory(new VirtualFileSystemFactory(path)); - } - - - private PublicKey decodePublicKey() throws Exception { - InputStream stream = new ClassPathResource("/keys/sftp_rsa.pub").getInputStream(); - byte[] decodeBuffer = Base64.decodeBase64(StreamUtils.copyToByteArray(stream)); - ByteBuffer bb = ByteBuffer.wrap(decodeBuffer); - int len = bb.getInt(); - byte[] type = new byte[len]; - bb.get(type); - if ("ssh-rsa".equals(new String(type))) { - BigInteger e = decodeBigInt(bb); - BigInteger m = decodeBigInt(bb); - RSAPublicKeySpec spec = new RSAPublicKeySpec(m, e); - return KeyFactory.getInstance("RSA").generatePublic(spec); - - } - else { - throw new IllegalArgumentException("Only supports RSA"); - } - } - - private BigInteger decodeBigInt(ByteBuffer bb) { - int len = bb.getInt(); - byte[] bytes = new byte[len]; - bb.get(bytes); - return new BigInteger(bytes); - } - - @Override - public boolean isAutoStartup() { - return PORT == this.port; - } - - @Override - public int getPhase() { - return Integer.MAX_VALUE; - } - - @Override - public void start() { - try { - server.start(); - this.running = true; - } - catch (IOException e) { - throw new IllegalStateException(e); - } - } - - @Override - public void stop(Runnable callback) { - stop(); - callback.run(); - } - - @Override - public void stop() { - if (this.running) { - try { - server.stop(false); - } - catch (IOException e) { - throw new IllegalStateException(e); - } - finally { - this.running = false; - } - } - } - - @Override - public boolean isRunning() { - return this.running; - } - - public SshServer getServer() { - return server; - } - -} diff --git a/sftp-upload-demo/src/test/java/com/sftp/SpringSftpUploadDemoApplicationTests.java b/sftp-upload-demo/src/test/java/com/sftp/SpringSftpUploadDemoApplicationTests.java deleted file mode 100644 index 008a344..0000000 --- a/sftp-upload-demo/src/test/java/com/sftp/SpringSftpUploadDemoApplicationTests.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.sftp; - -import static org.junit.Assert.assertEquals; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; -import java.util.stream.Collectors; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; - -import com.sftp.SftpConfig.UploadGateway; - -@RunWith(SpringRunner.class) -@SpringBootTest -@TestPropertySource(properties = { "sftp.port = 10022" }) -public class SpringSftpUploadDemoApplicationTests { - - @Autowired - private UploadGateway gateway; - - private static EmbeddedSftpServer server; - - private static Path sftpFolder; - - @BeforeClass - public static void startServer() throws Exception { - server = new EmbeddedSftpServer(); - server.setPort(10022); - sftpFolder = Files.createTempDirectory("SFTP_UPLOAD_TEST"); - server.afterPropertiesSet(); - server.setHomeFolder(sftpFolder); - // Starting SFTP - if (!server.isRunning()) { - server.start(); - } - } - - @Before - @After - public void cleanSftpFolder() throws IOException { - Files.walk(sftpFolder).filter(Files::isRegularFile).map(Path::toFile).forEach(File::delete); - } - - @Test - public void testUpload() throws IOException { - // Prepare phase - Path tempFile = Files.createTempFile("UPLOAD_TEST", ".csv"); - - // Prerequisites - assertEquals(0, Files.list(sftpFolder).count()); - - // test phase - gateway.upload(tempFile.toFile()); - - // Validation phase - List paths = Files.list(sftpFolder).collect(Collectors.toList()); - assertEquals(1, paths.size()); - assertEquals(tempFile.getFileName(), paths.get(0).getFileName()); - } - - @AfterClass - public static void stopServer() { - if (server.isRunning()) { - server.stop(); - } - } - -}