1

我正在使用 jgit 从在 kubernetes 容器中运行的 java 应用程序运行 git 命令,因此我希望允许自定义 ssh 密钥存储位置等。

我的第一种方法是使用 jsch 实现支持 ssh,但遇到了麻烦(我在这里检查了方法Using Keys with JGit to Access a Git Repository Securely并且没有运气)所以我通过 org 添加了 ssh 支持.eclipse.jgit.ssh.apache 工件。由于打包/分发的方式,使用外部 ssh 应用程序并不是一个真正的选择。

我没有太多运气找到信息,但假设我只想模仿 jsch 方法并替换调用中使用的会话工厂。最初我采用的方法是使用所需的 ssh 路径设置会话工厂

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

        return builder.build(null);

并将这个工厂传递给各种命令。

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();

但是,使用这种方法,像 clone 这样的命令将无法通过 git repo 进行身份验证,试图使用默认的 ssh 密钥。在调试器中执行此操作后,我发现在 clone 命令中,它正在生成一个 fetch 命令,但没有将会话工厂或会话传递给它,因此 fetch 只是构建了一个默认配置并且无法进行身份验证。

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

最终我决定只覆盖默认的会话工厂,这很有效,但不是真的。

SshSessionFactory.setInstance(sshSessionFactory);

这最终工作了一段时间,但随后分崩离析,无法从工厂创建新会话(我不知道为什么,但我不想覆盖默认实例,因此发布这个问题)

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

所以总而言之:自定义 ssh 会话创建并确保它通过调用其他命令的瓷命令持续存在的正确方法是什么?这是jgit的错误吗?我错过了什么,或者在这里做错了什么?

4

3 回答 3

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

上面的代码对我有用,只需要在id_rsa文件.ssh夹中有文件。并且密钥必须没有密码。仍在寻找一种通过密钥传递密码的方法。

于 2021-09-22T08:22:04.543 回答
0

我不认为你缺少任何东西。可以在命令上使用回调挂钩,您可以在其中插入配置代码。我从来没有和 MINA 一起工作过。我 问了一个类似的问题,但在这里从未得到答案。如果您知道如何做,请发布,因为这是一个特别具有挑战性的主题。

于 2021-06-04T00:06:04.917 回答
0

使用 JGit 版本 6.0.0.202111291000-r,我可以使用 Apache MINA SSHD 执行传输命令。为了这,

  • CustomSshSessionFactory在回调中设置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);

  }
});

  • 创建了SshdSessionFactory. 你也可以使用SshdSessionFactoryBuilder
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();
    }

}
  • 创建自定义实现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;
    }
}

在这里,需要注意的重要事项是

  • 通过自定义实现设置密码CredentialsProvider
  • 私钥作为文件输入提供给SshSessionFactory
于 2022-01-10T02:33:51.203 回答