Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Keys with JGit to Access a Git Repository Securely

Tags:

java

git

ssh

jsch

jgit

I'm using JGit to access a remote Git repo, and I need to use SSH for it. JGit uses JSch to provide secure access. However, I'm not sure how to set the key file and the knows hosts file for JGit. What I have tried is as follows.

Created a custom configuration of the SshSessionFactory, using by subclassing JSchConfigSessionFactory:

public class CustomJschConfigSessionFactory extends JschConfigSessionFactory {
    @Override
    protected void configure(OpenSshConfig.Host host, Session session) {
        session.setConfig("StrictHostKeyChecking", "yes");
    }
}

In the class which I access the remote Git repo, did the following:

CustomJschConfigSessionFactory jschConfigSessionFactory = new CustomJschConfigSessionFactory();

JSch jsch = new JSch();
try {
    jsch.addIdentity(".ssh/id_rsa");
    jsch.setKnownHosts(".ssh/known_hosts");
} catch (JSchException e) {
    e.printStackTrace();  
}
    SshSessionFactory.setInstance(jschConfigSessionFactory);

I can't figure out how to associate this JSch object with JGit so that it can successfully connect to the remote repository. When I try to clone it with JGit, I get the following exception:

org.eclipse.jgit.api.errors.TransportException: [email protected]:abc.org/test_repo.git: reject HostKey: git.test.com
at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:137)
at org.eclipse.jgit.api.CloneCommand.fetch(CloneCommand.java:178)
at org.eclipse.jgit.api.CloneCommand.call(CloneCommand.java:125)
at GitTest.cloneRepo(GitTest.java:109)
at GitTest.main(GitTest.java:223)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: org.eclipse.jgit.errors.TransportException: [email protected]:abc.org/test_repo.git: reject HostKey: git.test.com
at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:142)
at org.eclipse.jgit.transport.SshTransport.getSession(SshTransport.java:121)
at org.eclipse.jgit.transport.TransportGitSsh$SshFetchConnection.<init>(TransportGitSsh.java:248)
at org.eclipse.jgit.transport.TransportGitSsh.openFetch(TransportGitSsh.java:147)
at org.eclipse.jgit.transport.FetchProcess.executeImp(FetchProcess.java:136)
at org.eclipse.jgit.transport.FetchProcess.execute(FetchProcess.java:122)
at org.eclipse.jgit.transport.Transport.fetch(Transport.java:1104)
at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:128)
... 9 more
Caused by: com.jcraft.jsch.JSchException: reject HostKey: git.test.com
at com.jcraft.jsch.Session.checkHost(Session.java:748)
at com.jcraft.jsch.Session.connect(Session.java:321)
at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:116)
... 16 more

I have added the git.test.com entry to my /etc/hosts file. I have used the same code to access a git repo with a http url, so the code it working fine. It's the key handling part that is failing. Any idea on how to handle this?

like image 438
Izza Avatar asked Dec 03 '12 15:12

Izza


People also ask

Should I use SSH or https for Git?

While SSH is usually considered more secure, for basic usage of Github, HTTPS authentication with a password is acceptable enough. In fact, Github themselves defaults to and recommends most people use HTTPS.

Which SSH key will git use?

Since git just uses ssh to connect, it will use whichever key ssh would use to connect to the remote host. See the ~/. ssh/config file for details; the host block uses the IdentityFile directive to specify the private key to use. The ssh_config(5) manpage contains full details.


2 Answers

You need to override the getJSch method in your custom factory class:

class CustomConfigSessionFactory extends JschConfigSessionFactory
{
    @Override
    protected JSch getJSch(final OpenSshConfig.Host hc, FS fs) throws JSchException {
        JSch jsch = super.getJSch(hc, fs);
        jsch.removeAllIdentity();
        jsch.addIdentity( "/path/to/private/key" );
        return jsch;
    }
}

Calling jsch.removeAllIdentity is important; it doesn't seem to work without it.

A caveat: I wrote the above in Scala, and then translated it over to Java, so it might not be quite right. The original Scala is as follows:

class CustomConfigSessionFactory extends JschConfigSessionFactory
{
    override protected def getJSch( hc : OpenSshConfig.Host, fs : FS ) : JSch =
    {
        val jsch = super.getJSch(hc, fs)
        jsch.removeAllIdentity()
        jsch.addIdentity( "/path/to/private/key" )
        jsch
    }
}
like image 162
paulmdavies Avatar answered Oct 06 '22 00:10

paulmdavies


Jsch sesems to not like a known_hosts file in the hashed format-- it must conform to the format produced by:

ssh-keyscan -t rsa hostname >> ~/.ssh/known_hosts

e.g.

<hostname> ssh-rsa <longstring/longstring>

not:

 |1|<hashed hostname>= ecdsa-sha2-nistp256 <hashed fingerprint>=
like image 34
joshwa Avatar answered Oct 06 '22 01:10

joshwa