2

I'm running git commands using jgit from a java application running in a kubernetes container, so I want to allow customizing the ssh key storage location and the like.

My first approach was with ssh supported with the jsch implementation but ran into troubles(I checked the methodology here Using Keys with JGit to Access a Git Repository Securely and have had no luck with it) so I'm adding the ssh support via the org.eclipse.jgit.ssh.apache artifact. Using an external ssh app isn't really an option due to the way this is being packaged/distributed.

I haven't had much luck finding information but assume that I just want to be emulating the jsch approach and replacing the session factory used in calls. Initially the approach I took was setting up a session factory with the desired ssh path

        final SshdSessionFactoryBuilder builder = new SshdSessionFactoryBuilder();
        builder.setHomeDirectory(new File(homeDir))
                .setConfigFile((f)-> new File(f, "config"))
                .setSshDirectory(new File(sshDir));

        return builder.build(null);

and passing this factory to the various commands.

final CloneCommand cmd = Git.cloneRepository().setDirectory(new File(basePath))
                            .setURI(remotePath);
                    if (sshSessionFactory != null) {
                        cmd.setTransportConfigCallback(new TransportConfigCallback() {
                            @Override
                            public void configure(Transport transport) {
                                final SshTransport sshTransport = (SshTransport)transport;
                                ((SshTransport) transport).setSshSessionFactory(sshSessionFactory);
                            }
                        });
                    }
                    git = cmd.call();

However with this approach, commands like clone would fail to auth with the git repo, attempting to use the default ssh keys. On following this in the debugger I found that inside the clone command, it's generating a fetch command but isn't passing the session factory or session to it, so the fetch simply builds a default config and fails to auth.

2021-05-31 11:48:09,793 INFO  GitChainRepository.java:114 - Couldn't find git dir, creating it
2021-05-31 11:48:10,748 INFO  AbstractSecurityProviderRegistrar.java:112 - getOrCreateProvider(EdDSA) created instance of net.i2p.crypto.eddsa.EdDSASecurityProvider
2021-05-31 11:48:10,970 INFO  DefaultIoServiceFactoryFactory.java:67 - No detected/configured IoServiceFactoryFactory using Nio2ServiceFactoryFactory
2021-05-31 11:48:12,206 INFO  GitChainRepository.java:133 - Initialized by clone of remote
2021-05-31 11:48:12,207 INFO  GitChainRepository.java:159 - Prepping remote repo git@ghe.snip/gitchainstore-synctest.git
2021-05-31 11:48:12,318 WARN  LoggingUtils.java:634 - exceptionCaught(JGitClientSession[git@ghe.ca-tools.org/52.69.168.141:22])[state=Opened] SshException: Server key did not validate
org.apache.sshd.common.SshException: Server key did not validate
    at org.apache.sshd.client.session.AbstractClientSession.checkKeys(AbstractClientSession.java:583) ~[sshd-osgi-2.6.0.jar:2.6.0]
    at org.apache.sshd.common.session.helpers.AbstractSession.handleKexMessage(AbstractSession.java:611) ~[sshd-osgi-2.6.0.jar:2.6.0]
    at org.apache.sshd.common.session.helpers.AbstractSession.doHandleMessage(AbstractSession.java:500) ~[sshd-osgi-2.6.0.jar:2.6.0]
    at org.apache.sshd.common.session.helpers.AbstractSession.handleMessage(AbstractSession.java:428) ~[sshd-osgi-2.6.0.jar:2.6.0]
    at org.apache.sshd.common.session.helpers.AbstractSession.decode(AbstractSession.java:1463) ~[sshd-osgi-2.6.0.jar:2.6.0]
    at org.apache.sshd.common.session.helpers.AbstractSession.messageReceived(AbstractSession.java:388) ~[sshd-osgi-2.6.0.jar:2.6.0]
    at org.eclipse.jgit.internal.transport.sshd.JGitClientSession.messageReceived(JGitClientSession.java:197) ~[org.eclipse.jgit.ssh.apache-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
    at org.apache.sshd.common.session.helpers.AbstractSessionIoHandler.messageReceived(AbstractSessionIoHandler.java:64) ~[sshd-osgi-2.6.0.jar:2.6.0]
    at org.apache.sshd.common.io.nio2.Nio2Session.handleReadCycleCompletion(Nio2Session.java:358) ~[sshd-osgi-2.6.0.jar:2.6.0]
    at org.apache.sshd.common.io.nio2.Nio2Session$1.onCompleted(Nio2Session.java:335) ~[sshd-osgi-2.6.0.jar:2.6.0]
    at org.apache.sshd.common.io.nio2.Nio2Session$1.onCompleted(Nio2Session.java:332) ~[sshd-osgi-2.6.0.jar:2.6.0]
    at org.apache.sshd.common.io.nio2.Nio2CompletionHandler.lambda$completed$0(Nio2CompletionHandler.java:38) ~[sshd-osgi-2.6.0.jar:2.6.0]
    at java.security.AccessController.doPrivileged(Native Method) ~[?:?]
    at org.apache.sshd.common.io.nio2.Nio2CompletionHandler.completed(Nio2CompletionHandler.java:37) [sshd-osgi-2.6.0.jar:2.6.0]
    at sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:127) [?:?]
    at sun.nio.ch.Invoker$2.run(Invoker.java:219) [?:?]
    at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112) [?:?]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
    at java.lang.Thread.run(Thread.java:834) [?:?]
2021-05-31 11:48:12,331 INFO  SessionHelper.java:1034 - Disconnecting(JGitClientSession[git@ghe.ca-tools.org/52.69.168.141:22]): SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE - Server key did not validate

org.eclipse.jgit.api.errors.TransportException: git@ghe.snip/gitchainstore-synctest.git: Server key did not validate

    at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:224)
    at org.eclipse.jgit.api.PullCommand.call(PullCommand.java:263)
    at snip.GitChainRepository.setupRemote(GitChainRepository.java:173)
    at snip.GitChainRepository.start(GitChainRepository.java:144)
    at snip.GitChainRepositoryTest.setupGit(GitChainRepositoryTest.java:59)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.RunBefores.invokeMethod(RunBefores.java:33)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Caused by: org.eclipse.jgit.errors.TransportException: git@ghe.snip/gitchainstore-synctest.git: Server key did not validate
    at org.eclipse.jgit.transport.sshd.SshdSessionFactory.getSession(SshdSessionFactory.java:248)
    at org.eclipse.jgit.transport.sshd.SshdSessionFactory.getSession(SshdSessionFactory.java:1)
    at org.eclipse.jgit.transport.SshTransport.getSession(SshTransport.java:107)
    at org.eclipse.jgit.transport.TransportGitSsh$SshFetchConnection.<init>(TransportGitSsh.java:281)
    at org.eclipse.jgit.transport.TransportGitSsh.openFetch(TransportGitSsh.java:153)
    at org.eclipse.jgit.transport.FetchProcess.executeImp(FetchProcess.java:142)
    at org.eclipse.jgit.transport.FetchProcess.execute(FetchProcess.java:94)
    at org.eclipse.jgit.transport.Transport.fetch(Transport.java:1309)
    at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:213)
    ... 31 more
Caused by: org.apache.sshd.common.SshException: Server key did not validate
    at org.apache.sshd.common.future.AbstractSshFuture.verifyResult(AbstractSshFuture.java:126)
    at org.apache.sshd.client.future.DefaultAuthFuture.verify(DefaultAuthFuture.java:39)
    at org.apache.sshd.client.future.DefaultAuthFuture.verify(DefaultAuthFuture.java:32)
    at org.apache.sshd.common.future.VerifiableFuture.verify(VerifiableFuture.java:68)
    at org.eclipse.jgit.transport.sshd.SshdSession.connect(SshdSession.java:164)
    at org.eclipse.jgit.transport.sshd.SshdSession.connect(SshdSession.java:99)
    at org.eclipse.jgit.transport.sshd.SshdSessionFactory.getSession(SshdSessionFactory.java:235)
    ... 39 more
Caused by: org.apache.sshd.common.SshException: Server key did not validate
    at org.apache.sshd.client.session.AbstractClientSession.checkKeys(AbstractClientSession.java:583)
    at org.apache.sshd.common.session.helpers.AbstractSession.handleKexMessage(AbstractSession.java:611)
    at org.apache.sshd.common.session.helpers.AbstractSession.doHandleMessage(AbstractSession.java:500)
    at org.apache.sshd.common.session.helpers.AbstractSession.handleMessage(AbstractSession.java:428)
    at org.apache.sshd.common.session.helpers.AbstractSession.decode(AbstractSession.java:1463)
    at org.apache.sshd.common.session.helpers.AbstractSession.messageReceived(AbstractSession.java:388)
    at org.eclipse.jgit.internal.transport.sshd.JGitClientSession.messageReceived(JGitClientSession.java:197)
    at org.apache.sshd.common.session.helpers.AbstractSessionIoHandler.messageReceived(AbstractSessionIoHandler.java:64)
    at org.apache.sshd.common.io.nio2.Nio2Session.handleReadCycleCompletion(Nio2Session.java:358)
    at org.apache.sshd.common.io.nio2.Nio2Session$1.onCompleted(Nio2Session.java:335)
    at org.apache.sshd.common.io.nio2.Nio2Session$1.onCompleted(Nio2Session.java:332)
    at org.apache.sshd.common.io.nio2.Nio2CompletionHandler.lambda$completed$0(Nio2CompletionHandler.java:38)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at org.apache.sshd.common.io.nio2.Nio2CompletionHandler.completed(Nio2CompletionHandler.java:37)
    at java.base/sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:127)
    at java.base/sun.nio.ch.Invoker$2.run(Invoker.java:219)
    at java.base/sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.base/java.lang.Thread.run(Thread.java:834)


Process finished with exit code -1

Eventually I settled to just overriding the default session factory, which sort of works, but not really.

SshSessionFactory.setInstance(sshSessionFactory);

This ends up working for a bit but then falls apart unable to create new sessions from the factory(I haven't figured why but I'd prefer not to be overriding the default instance anyway hence posting this question)

org.eclipse.jgit.api.errors.TransportException: git@ghe.snip/gitchainstore-synctest.git: Apache MINA sshd session factory is closing down; cannot create new ssh sessions on this factory
        at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:224) ~[org.eclipse.jgit-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at org.eclipse.jgit.api.PullCommand.call(PullCommand.java:263) ~[org.eclipse.jgit-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at snip.GitChainRepository.updateRemote(GitChainRepository.java:190) ~[core-0.1.0-28.jar:?]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) [?:?]
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305) [?:?]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305) [?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
        at java.lang.Thread.run(Thread.java:829) [?:?]
Caused by: org.eclipse.jgit.errors.TransportException: git@ghe.snip/gitchainstore-synctest.git: Apache MINA sshd session factory is closing down; cannot create new ssh sessions on this factory
        at org.eclipse.jgit.transport.sshd.SshdSessionFactory.getSession(SshdSessionFactory.java:248) ~[org.eclipse.jgit.ssh.apache-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at org.eclipse.jgit.transport.sshd.SshdSessionFactory.getSession(SshdSessionFactory.java:1) ~[org.eclipse.jgit.ssh.apache-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at org.eclipse.jgit.transport.SshTransport.getSession(SshTransport.java:107) ~[org.eclipse.jgit-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at org.eclipse.jgit.transport.TransportGitSsh$SshFetchConnection.<init>(TransportGitSsh.java:281) ~[org.eclipse.jgit-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at org.eclipse.jgit.transport.TransportGitSsh.openFetch(TransportGitSsh.java:153) ~[org.eclipse.jgit-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at org.eclipse.jgit.transport.FetchProcess.executeImp(FetchProcess.java:142) ~[org.eclipse.jgit-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at org.eclipse.jgit.transport.FetchProcess.execute(FetchProcess.java:94) ~[org.eclipse.jgit-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at org.eclipse.jgit.transport.Transport.fetch(Transport.java:1309) ~[org.eclipse.jgit-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:213) ~[org.eclipse.jgit-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        ... 8 more
Caused by: java.io.IOException: Apache MINA sshd session factory is closing down; cannot create new ssh sessions on this factory
        at org.eclipse.jgit.transport.sshd.SshdSessionFactory.register(SshdSessionFactory.java:272) ~[org.eclipse.jgit.ssh.apache-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at org.eclipse.jgit.transport.sshd.SshdSessionFactory.getSession(SshdSessionFactory.java:234) ~[org.eclipse.jgit.ssh.apache-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at org.eclipse.jgit.transport.sshd.SshdSessionFactory.getSession(SshdSessionFactory.java:1) ~[org.eclipse.jgit.ssh.apache-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at org.eclipse.jgit.transport.SshTransport.getSession(SshTransport.java:107) ~[org.eclipse.jgit-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at org.eclipse.jgit.transport.TransportGitSsh$SshFetchConnection.<init>(TransportGitSsh.java:281) ~[org.eclipse.jgit-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at org.eclipse.jgit.transport.TransportGitSsh.openFetch(TransportGitSsh.java:153) ~[org.eclipse.jgit-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at org.eclipse.jgit.transport.FetchProcess.executeImp(FetchProcess.java:142) ~[org.eclipse.jgit-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at org.eclipse.jgit.transport.FetchProcess.execute(FetchProcess.java:94) ~[org.eclipse.jgit-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at org.eclipse.jgit.transport.Transport.fetch(Transport.java:1309) ~[org.eclipse.jgit-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:213) ~[org.eclipse.jgit-5.11.0.202103091610-r.jar:5.11.0.202103091610-r]
        ... 8 more

So in conclusion: What is the correct way to customize ssh session creation and make sure it persists through porcelain commands that call other commands? Is this a bug with jgit? Am I missing something, or doing something here wrong?

juhanic
  • 805
  • 8
  • 16

5 Answers5

3
File sshDir = new File(FS.DETECTED.userHome(), "/.ssh");
SshdSessionFactory sshSessionFactory = new SshdSessionFactoryBuilder()
        .setPreferredAuthentications("publickey")
        .setHomeDirectory(FS.DETECTED.userHome())
        .setSshDirectory(sshDir)
        .build(null);

The above code worked for me, just need to have the id_rsa file in the .ssh folder. and the key has to be without a passphrase. Still looking for a way to pass a passphrase with a key.

You can use this link for better understanding: https://medium.com/@pratikshende99/how-to-clone-git-repo-with-ssh-url-by-executing-command-through-java-using-processbuilder-e162010266f5

  • This is working for me as well. And I'm using id_ed25519 key. – marverix May 30 '22 at 08:06
  • I ended up using this(which is more or less as I had it). I'm not really happy with having to set the home directory to make it work, but it does work once you brute force everything into the home directory(which doesn't exactly exist on the docker container, and why I expected the ssh directory to be applied throughout) – juhanic Jul 01 '22 at 07:29
  • you can set the passphrase for the key by setting a KeyPasswordProvider to the builder. .setKeyPasswordProvider(cp -> new IdentityPasswordProvider(cp) { @Override protected char[] getPassword(URIish uri, String message) { return passphrase.toCharArray(); } }) – Priyal Jun 11 '23 at 16:47
1

With the JGit version 6.0.0.202111291000-r, I am able to execute a transport command using Apache MINA SSHD. For this,

  • Set CustomSshSessionFactory in the callback for TransportCommand.
cmd.setTransportConfigCallback(
transport -> {
  if(transport instanceOf SshTransport) {
    SshTransport sshTransport = (SshTransport) transport;
    // Set passphrase using a CustomCredentialsProvider
    sshTransport.setCredentialsProvider(new CustomCredentialProvider(passphrase));
    // Provide private key to `CustomSshSessionFactory`
    SshSessionFactory sshFactory = new CustomSshSessionFactory(privatekey);
    sshTransport.setSshSessionFactory(sshFactory);

  }
});

  • Created implementation of SshdSessionFactory. You can use SshdSessionFactoryBuilder as well.
public final class CustomSshSessionFactory extends SshdSessionFactory {


    public static final Path SSH_DIR = Path.of("some-path");

    private final Path privateKeyFile;
    private final byte[] sshKey;

    public CustomSshSessionFactory(byte[] sshKey) {
        this.sshKey = sshKey;
        privateKeyFile = Path.of("some-name", SSH_DIR.toString());
    }

    @Override
    public File getSshDirectory() {
        try {
            return Files.createDirectories(SSH_DIR).toFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

// Return paths to private key files
    @Override
    protected List<Path> getDefaultIdentities(File sshDir) {
        try {
            Files.write(privateKeyFile, sshKey);
            return Collections.singletonList(privateKeyFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Collections.emptyList();
    }

}
  • Created custom implementation of CredentialsProvider
public class CustomCredentialProvider extends CredentialsProvider {

    private final List<String> stringStore;

    private final String passphrase;

    public CustomCredentialProvider(String passphrase) {
        this.passphrase = passphrase;
    }

    @Override
    public boolean isInteractive() {
        // Set this according to your requirement
        return false;
    }

    @Override
    public boolean supports(CredentialItem... items) {
        // Set this according to your requirement
        return true;
    }

    @Override
    public boolean get(URIish uri, CredentialItem... items)
            throws UnsupportedCredentialItem {

        for (CredentialItem item : items) {
            if (item instanceof CredentialItem.InformationalMessage) {
                continue;
            }
            if (item instanceof CredentialItem.YesNoType) {
                // Set this according to your requirement
                ((CredentialItem.YesNoType) item).setValue(true);
            } else if (item instanceof CredentialItem.CharArrayType) {
                if (passphrase != null) {
                    ((CredentialItem.CharArrayType) item)
                            .setValue(passphrase.toCharArray());
                } else {
                    return false;
                }
            } else if (item instanceof CredentialItem.StringType) {
                if (passphrase != null) {
                    ((CredentialItem.StringType) item)
                            .setValue(passphrase);
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }
        return true;
    }
}

Here, important things to note are

  • setting passphrase through custom implementations of CredentialsProvider
  • private key is provided as a file input to SshSessionFactory
Omkar Shetkar
  • 3,488
  • 5
  • 35
  • 50
0

I do not think you are missing anything. There is a callback hook that can be used on the commands, where you can insert the configuration code. I never got that to work with MINA. I asked a similar question, but never got an answer here. Please post if you find out how to do it, as this is a particularly challenging subject.

Jörn Guy Süß
  • 1,408
  • 11
  • 18
0

I've been facing the same problem for several days. For me the solution was adding known_hosts file to my custom directory for ssh keys. Also make sure that your keys have default names.

  • Could you elaborate your answer, stating the generic structure of the `known_hosts` file, and where it should be placed? – Wrichik Basu Mar 20 '22 at 16:44
  • So, I had the same code as in answer by Pratik Shende. The only difference being, instead of default `/.ssh` I wanted to use ssh keys from my custom location. for example `/.ssh/custom-dir` I changed value of `sshDir` to appropriate one, however I was getting **Server key did not validate** error. finally when I placed `known_hosts` file in `/.ssh/custom-dir` it worked. Regarding the structure of `known_hosts` file you can find it here: [link](https://www.techrepublic.com/article/how-to-easily-add-an-ssh-fingerprint-to-your-knownhosts-file-in-linux/) – Vakhtang Donadze Mar 21 '22 at 17:19
  • Surely there are other, more complex solutions trough `CredentialsProvider` if you dont want to manually manage `known_hosts` but for the basic code using `SshdSessionFactoryBuilder` just placing `known_hosts` in the same directory as ssh keys worked for me. – Vakhtang Donadze Mar 21 '22 at 17:24
0

With following one can set the passphrase for the private key while building the SshdSessionFactory.

  File sshDir = new File(FS.DETECTED.userHome(), "/.ssh");
  SshdSessionFactory sshSessionFactory = new SshdSessionFactoryBuilder().setPreferredAuthentications("publickey")
    .setHomeDirectory(FS.DETECTED.userHome()).setSshDirectory(sshDir)
    .setKeyPasswordProvider(cp -> new IdentityPasswordProvider(cp)
    {
      @Override
      protected char[] getPassword(URIish uri, String message)
      {
        return passphrase.toCharArray();
      }
    }).build(null);

How to set the KeyPasswordProvider with Kotlin (Original content before edit)

sshdSessionFactoryBuilder.setKeyPasswordProvider {
                        object : IdentityPasswordProvider(it) {
                            override fun getPassword(uri: URIish?, message: String?): CharArray {
                                return sshPassword.toCharArray()
                            }

                        }
                    }
Priyal
  • 444
  • 5
  • 18
JMCui
  • 11
  • 3
  • 2
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 05 '22 at 17:34