Search code examples
javaapache-sshd

How to write file into Apache SSHD server?


EXPLANATION:

I am building a test tool for my colleagues. I have several "mock" in-memory back-ends that they will need to use to run integration tests.

Therefore, I need to run SSH Server with the ability to upload/download a file.

The basic use-cases are the following:

  • Upload a file, download file via Apache Camel route
  • Upload a file, transfer file to a different folder via Apache Camel route, download file to verify transformation, content

QUESTION:

I have Apache SSHD Server written:

Server implementation example SshServer.java:

package com.example.sshd;

import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.scp.ScpCommandFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.file.Files;

public class SSHServer {

    private SshServer sshServer;
    private static final Logger logger = LoggerFactory.getLogger(SSHServer.class);

    public SSHServer() throws IOException {
        sshServer = SshServer.setUpDefaultServer();
        sshServer.setHost("127.0.0.1");
        sshServer.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(Files.createTempFile("host_file", ".ser").toAbsolutePath()));
        sshServer.setCommandFactory(new ScpCommandFactory());
        sshServer.setPasswordAuthenticator((username, password, serverSession) -> {
            logger.debug("authenticating: {} password: {}", username, password);
            return username != null && "changeit".equals(password);
        });
    }

    public void startServer() throws IOException{
        sshServer.start();
    }

    public void stopServer() throws IOException {
        sshServer.stop();
    }
}

I tried:

  • Find JavaDoc
  • Find similar questions/solutions on StackOverflow
  • Read Apache SSHD documentation on GitHub

I couldn't find an answer so far. I found this post, and it looks like I need to have SSH Client as well. Am I on the right track?

  • Do I need SSH Client to write a file to SSH Server?
  • How can I write a file while running the Apache SSHD server?

Solution

  • Apparently yes.

    As I didn't have an SSH client, I have to create both client and server.

    Example of file upload in Kotlin:

    fun upload(file: File) {
        val creator = ScpClientCreator.instance()
        val scpClient = creator.createScpClient(session())
        scpClient.upload(Paths.get(file.absolutePath), file.name)
    }
    

    SSH Server creation:

    fun setupServer(host: String, port: Int, rootDir: File, userName: String, pwd: String): SshServer {
        val sshd = SshServer.setUpDefaultServer()
        sshd.keyPairProvider = SimpleGeneratorHostKeyProvider(File(rootDir, "sshd_key.ser").toPath())
        sshd.fileSystemFactory = VirtualFileSystemFactory(Paths.get(rootDir.absolutePath))
        sshd.port = port
        sshd.host = host
        sshd.passwordAuthenticator = PasswordAuthenticator { username: String, password: String, _: ServerSession? -> username == userName && password == pwd }
        sshd.commandFactory = ScpCommandFactory()
        val factoryList: MutableList<SubsystemFactory> = ArrayList()
        factoryList.add(SftpSubsystemFactory())
        sshd.subsystemFactories = factoryList
        return sshd
    }
    

    SSH Client creation:

    fun setupClient(): SshClient {
        return SshClient.setUpDefaultClient()
    }
    
    // Session for scp client
    fun session(): ClientSession {
        val session = client.connect(userName, server.host, server.port).verify().session
        session.addPasswordIdentity(password)
        session.auth().verify().isSuccess
        return session
    }