eclipse-jgit / jgit

JGit, the Java implementation of git
https://www.eclipse.org/jgit/
Other
121 stars 34 forks source link

Why do I need a credentialsProvider if I've configured the SshSessionFactory? #72

Closed devvthedev closed 1 month ago

devvthedev commented 1 month ago

Hello,

I'm using the following JGit and Apache MINA dependencies in my project:

implementation "org.eclipse.jgit:org.eclipse.jgit:6.10.0.202406032230-r"
implementation "org.eclipse.jgit:org.eclipse.jgit.ssh.apache:6.10.0.202406032230-r"
implementation "org.apache.sshd:sshd-git:2.13.1"

I've created a default org.apache.sshd.client.SshClient with: SshClient sshClient = SshClient.setUpDefaultClient();

and then set an instance of the GitSshdSessionFactory on JGits SshSessionFactory: SshSessionFactory.setInstance(new GitSshdSessionFactory(sshClient));


By default the sshClient is reading the SSH keys I have stored in the ~/.ssh folder where the config file has the following configuration:

Host github.com
  IdentityFile ~/.ssh/my-ssh-key

I am using a passphrase-less private SSH key.



The question I have is around JGits Git push command call when talking back to the remote repository.

For example,

  1. Given I have cloned a repository on my machine with SSH in a terminal:

git clone git@github.com:devvthedev/my-project.git

  1. Made some changes to the repo

  2. Opened the repo using JGit with Git.open(...) and get a Git object back

  3. Staged the changes I made and committed them:

git.add()
    .addFilepattern(".")
    .call();
git.commit()
    .setCommitter(new PersonIdent("me", "me@example.com"))
    .setMessage("message")
    .call();
  1. When I try to push those changes with JGit:
git.push()
    .call();

I get the following error:

Caused by: org.eclipse.jgit.errors.TransportException: Unable to connect
        at org.apache.sshd.git.transport.GitSshdSessionFactory.getSession(GitSshdSessionFactory.java:134)
        at org.eclipse.jgit.transport.SshTransport.getSession(SshTransport.java:107)
        at org.eclipse.jgit.transport.TransportGitSsh$SshPushConnection.<init>(TransportGitSsh.java:356)
        at org.eclipse.jgit.transport.TransportGitSsh.openPush(TransportGitSsh.java:157)
        at org.eclipse.jgit.transport.PushProcess.execute(PushProcess.java:140)
        at org.eclipse.jgit.transport.Transport.push(Transport.java:1555)
        at org.eclipse.jgit.api.PushCommand.call(PushCommand.java:158)
        ... 2 more
Caused by: java.lang.NullPointerException: Cannot invoke "org.eclipse.jgit.transport.CredentialsProvider.isInteractive()" because "credentialsProvider" is null
        at org.apache.sshd.git.transport.GitSshdSession.<init>(GitSshdSession.java:55)
        at org.apache.sshd.git.transport.GitSshdSessionFactory$1.<init>(GitSshdSessionFactory.java:90)
        at org.apache.sshd.git.transport.GitSshdSessionFactory.getSession(GitSshdSessionFactory.java:90)
        ... 8 more


If I provide a CredentialsProvider with the git user and no password:

git.push()
    .setCredentialsProvider(new UsernamePasswordCredentialsProvider("git", ""))
    .call();

It works!

So my question is - why is a CredentialsProvider required given I have configured a SshSessionFactory instance?

Or is this a question that should be asked to the Apache MINA SSHD Project maintainers?

Thank you

tomaswolf commented 1 month ago

Given that the stack trace shows that this NPE is from org.apache.sshd.git.transport.GitSshdSession: yes, this is a question for the Apache MINA sshd maintainers.

That said, JGit has its own integration with Apache MINA sshd in bundle org.eclipse.jgit.ssh.apache, which is tailored to the needs of JGit, works with the latest JGit versions, can do connections through SOCKS or HTTP CONNECT proxies, and has support for PKCS#11 hardware security modules (like YubiKey PIV). If you add org.eclipse.jgit.ssh.apache.agent you even have integration with SSH agents on Windows, Linux, and OS X.

devvthedev commented 1 month ago

Thanks @tomaswolf will see what they say 👍