Использование ключей с JGit для безопасного доступа к хранилищу Git
Я использую JGit для доступа к удаленному репо Git, и мне нужно использовать SSH. JGit использует JSch для обеспечения безопасного доступа. Однако я не уверен, как установить файл ключа и файл hosts для JGit. Я попытался сделать следующее.
Создал пользовательскую конфигурацию SshSessionFactory, используя подклассы JSchConfigSessionFactory:
public class CustomJschConfigSessionFactory extends JschConfigSessionFactory {
@Override
protected void configure(OpenSshConfig.Host host, Session session) {
session.setConfig("StrictHostKeyChecking", "yes");
}
}
В классе, к которому я обращаюсь к удаленному репозиторию Git, сделал следующее:
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);
Я не могу понять, как связать этот объект JSch с JGit, чтобы он мог успешно подключиться к удаленному репозиторию. Когда я пытаюсь клонировать его с помощью JGit, я получаю следующее исключение:
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
Я добавил запись git.test.com в мой файл /etc/hosts
. Я использовал тот же код для доступа к репо Git с URL-адресом http, поэтому код работает нормально. Это ключевая часть обработки, которая терпит неудачу. Любая идея о том, как справиться с этим?
Ответы
Ответ 1
Удалось найти проблему. Открытый ключ на стороне сервера имел другое имя, отличное от обычного id_rsa.pub, в то время как закрытый ключ на моей стороне был id_rsa. JSch ожидает, что по умолчанию открытый ключ будет иметь то же имя, что и закрытый ключ плюс суффикс .pub. Использование пары ключей с общим именем (например: private = key_1 и public = key_1.pub) решает проблему.
Ответ 2
Вам необходимо переопределить метод getJSch
в вашем пользовательском классе factory:
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;
}
}
Вызов jsch.removeAllIdentity
важен; он не работает без него.
Предостережение: я написал выше в Scala, а затем перевел его на Java, так что это может быть не совсем правильно. Оригинал Scala выглядит следующим образом:
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
}
}
Ответ 3
Jsch sesems не похож на файл known_hosts в хэшированном формате - он должен соответствовать формату, создаваемому:
ssh-keyscan -t rsa hostname >> ~/.ssh/known_hosts
например.
<hostname> ssh-rsa <longstring/longstring>
не
|1|<hashed hostname>= ecdsa-sha2-nistp256 <hashed fingerprint>=