From 851213adf81a233f1c7e2d806e97c3f7feea65ff Mon Sep 17 00:00:00 2001 From: Stewart Borle Date: Mon, 18 Nov 2024 15:47:42 +0800 Subject: [PATCH] Resolve NeoForge equivalent of 'https://github.com/pcal43/fastback/issues/260 ed25519 keys are not support in fasback-forge' At-least I believe it does. Uploading was failing with a jgit error aboud failing to negotiate the algorithm. Uploading to gitea and github now work after this change, which indicates to me that this issue is resolved. However, org.apache.sshd goes missing in development environments, and the SshHacks fix does not work anymore because of the library change. I've made an issue in architectury-loom for this: https://github.com/architectury/architectury-loom/issues/248 In addition, the error thrown due to org.apache.sshd going missing is now being logged, but will not prevent fastback from loading. Allowing the development environment to still be used without support for ssh. --- .../pcal/fastback/logging/Log4jLogger.java | 5 + .../pcal/fastback/logging/SystemLogger.java | 2 + .../java/net/pcal/fastback/mod/ModImpl.java | 13 +- neoforge/build.gradle | 23 +++- .../mod/neoforge/ForgeCommonProvider.java | 1 - .../mod/neoforge/Slf4jSystemLogger.java | 5 + .../pcal/fastback/mod/neoforge/SshHacks.java | 113 ------------------ 7 files changed, 38 insertions(+), 124 deletions(-) delete mode 100644 neoforge/src/main/java/net/pcal/fastback/mod/neoforge/SshHacks.java diff --git a/common/src/main/java/net/pcal/fastback/logging/Log4jLogger.java b/common/src/main/java/net/pcal/fastback/logging/Log4jLogger.java index 68636615..4abcd1b4 100644 --- a/common/src/main/java/net/pcal/fastback/logging/Log4jLogger.java +++ b/common/src/main/java/net/pcal/fastback/logging/Log4jLogger.java @@ -54,6 +54,11 @@ public void warn(String message) { this.log4j.warn(message); } + @Override + public void warn(String message, Throwable t) { + this.log4j.warn(message, t); + } + @Override public void info(String message) { this.log4j.info(message); diff --git a/common/src/main/java/net/pcal/fastback/logging/SystemLogger.java b/common/src/main/java/net/pcal/fastback/logging/SystemLogger.java index 8fcc60c8..4d7266f5 100644 --- a/common/src/main/java/net/pcal/fastback/logging/SystemLogger.java +++ b/common/src/main/java/net/pcal/fastback/logging/SystemLogger.java @@ -44,6 +44,8 @@ default void error(Throwable e) { void warn(String message); + void warn(String message, Throwable t); + void info(String message); void debug(String message); diff --git a/common/src/main/java/net/pcal/fastback/mod/ModImpl.java b/common/src/main/java/net/pcal/fastback/mod/ModImpl.java index 69b6df30..0082ca53 100644 --- a/common/src/main/java/net/pcal/fastback/mod/ModImpl.java +++ b/common/src/main/java/net/pcal/fastback/mod/ModImpl.java @@ -30,6 +30,7 @@ import java.nio.file.Path; import java.util.Collection; import java.util.Map; +import java.util.ServiceConfigurationError; import static java.nio.file.Files.createTempDirectory; import static java.util.Objects.requireNonNull; @@ -162,10 +163,14 @@ public void onInitialize() { syslog().info("git-lfs is installed: " + gitLfsVersion); } } - if (SshSessionFactory.getInstance() == null) { - syslog().warn("An ssh provider was not initialized for jgit. Operations on a remote repo over ssh will fail."); - } else { - syslog().info("SshSessionFactory: " + SshSessionFactory.getInstance().toString()); + try { + if (SshSessionFactory.getInstance() == null) { + syslog().warn("An ssh provider was not initialized for jgit. Operations on a remote repo over ssh will fail."); + } else { + syslog().info("SshSessionFactory: " + SshSessionFactory.getInstance().toString()); + } + } catch (Exception | ServiceConfigurationError e) { + syslog().warn("An ssh provider was not initialized for jgit. Operations on a remote repo over ssh will fail.", e); } syslog().debug("onInitialize complete"); } diff --git a/neoforge/build.gradle b/neoforge/build.gradle index 91d65a84..e4196efd 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -41,14 +41,25 @@ dependencies { forgeRuntimeLibrary implementation("org.eclipse.jgit:org.eclipse.jgit:${project.jgit_version}") { transitive = false } shadowCommon("org.eclipse.jgit:org.eclipse.jgit:${project.jgit_version}") { transitive = false } - forgeRuntimeLibrary runtimeOnly("org.eclipse.jgit:org.eclipse.jgit.ssh.jsch:${project.jgit_version}") { transitive = false; } - shadowCommon("org.eclipse.jgit:org.eclipse.jgit.ssh.jsch:${project.jgit_version}") { transitive = false } - - forgeRuntimeLibrary runtimeOnly('com.jcraft:jsch:0.1.55') - shadowCommon('com.jcraft:jsch:0.1.55') - forgeRuntimeLibrary runtimeOnly("com.googlecode.javaewah:JavaEWAH:${project.JavaEWAH_version}") { transitive = false } shadowCommon("com.googlecode.javaewah:JavaEWAH:${project.JavaEWAH_version}") { transitive = false } + + // https://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit.ssh.apache + forgeRuntimeLibrary runtimeOnly("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:${project.jgit_version}") { transitive = false } + shadowCommon("org.eclipse.jgit:org.eclipse.jgit.ssh.apache:${project.jgit_version}") { transitive = false } + + // https://mvnrepository.com/artifact/org.apache.sshd/sshd-core + forgeRuntimeLibrary runtimeOnly("org.apache.sshd:sshd-core:${project.apache_sshd_version}") { transitive = false } + shadowCommon("org.apache.sshd:sshd-core:${project.apache_sshd_version}") { transitive = false } + + // https://mvnrepository.com/artifact/org.apache.sshd/sshd-common + forgeRuntimeLibrary runtimeOnly("org.apache.sshd:sshd-common:${project.apache_sshd_version}") { transitive = false } + shadowCommon("org.apache.sshd:sshd-common:${project.apache_sshd_version}") { transitive = false } + + // this enables ed25519 support in apache_sshd + // https://github.com/apache/mina-sshd/blob/dfa109b7b535d64e8ee395ddd0419e7696fb24ee/docs/dependencies.md + forgeRuntimeLibrary runtimeOnly("net.i2p.crypto:eddsa:${project.eddsa_version}") { transitive = false } + shadowCommon("net.i2p.crypto:eddsa:${project.eddsa_version}") { transitive = false } } processResources { diff --git a/neoforge/src/main/java/net/pcal/fastback/mod/neoforge/ForgeCommonProvider.java b/neoforge/src/main/java/net/pcal/fastback/mod/neoforge/ForgeCommonProvider.java index 57ef6a02..8d827c6b 100644 --- a/neoforge/src/main/java/net/pcal/fastback/mod/neoforge/ForgeCommonProvider.java +++ b/neoforge/src/main/java/net/pcal/fastback/mod/neoforge/ForgeCommonProvider.java @@ -97,7 +97,6 @@ void onInitialize() { this.lifecycleListener = MinecraftProvider.register(this); syslog().debug("registered backup command"); this.lifecycleListener.onInitialize(); - SshHacks.ensureSshSessionFactoryIsAvailable(); syslog().info("Fastback initialized"); syslog().warn("------------------------------------------------------------------------------------"); syslog().warn("Thanks for trying the new Forge version of Fastback. For help, go to:"); diff --git a/neoforge/src/main/java/net/pcal/fastback/mod/neoforge/Slf4jSystemLogger.java b/neoforge/src/main/java/net/pcal/fastback/mod/neoforge/Slf4jSystemLogger.java index b1831a40..f388be5b 100644 --- a/neoforge/src/main/java/net/pcal/fastback/mod/neoforge/Slf4jSystemLogger.java +++ b/neoforge/src/main/java/net/pcal/fastback/mod/neoforge/Slf4jSystemLogger.java @@ -38,6 +38,11 @@ public void warn(String message) { this.slf4j.warn(message); } + @Override + public void warn(String message, Throwable t) { + this.slf4j.warn(message, t); + } + @Override public void info(String message) { this.slf4j.info(message); diff --git a/neoforge/src/main/java/net/pcal/fastback/mod/neoforge/SshHacks.java b/neoforge/src/main/java/net/pcal/fastback/mod/neoforge/SshHacks.java deleted file mode 100644 index 11b082b6..00000000 --- a/neoforge/src/main/java/net/pcal/fastback/mod/neoforge/SshHacks.java +++ /dev/null @@ -1,113 +0,0 @@ -package net.pcal.fastback.mod.neoforge; - -import org.eclipse.jgit.transport.SshSessionFactory; - -import java.lang.reflect.InvocationTargetException; - -import static net.pcal.fastback.logging.SystemLogger.syslog; - -public class SshHacks { - - /** - * This is necessary because JGit looks for it's SshSessionFactory with java.util.ServiceLoader, and that - * just doesn't seem to be something that Forge is willing to accommodate. - */ - public static void ensureSshSessionFactoryIsAvailable() { - try { - if (SshSessionFactory.getInstance() == null) { - try { - final String clazz = "org.eclipse.jgit.transport.ssh.jsch.JschConfigSessionFactory"; - SshSessionFactory.setInstance((SshSessionFactory) Class.forName(clazz).getConstructor().newInstance()); - // AFAICT this only happens in Intellij. Something about shadowJar and relocate isn't working in dev environments. - // Seems fine in the launcher. - syslog().warn("A SshSessionFactory was not located via java services; a " + clazz + " has been installed manually. This is probably ok."); - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | - NoSuchMethodException | InvocationTargetException ohwell) { - syslog().error("Unable to manually set SshSessionFactory. SSH connections will probably not work.", ohwell); - } - } - // - } catch (Error err) { - syslog().error("WAT", err); - } - } - - //JschConfigSessionFactory csf = new JschConfigSessionFactory(); - //SshSessionFactory.setInstance(csf); - // This works fine but the jsch provider doesn't support ed25519 keys; for that we need to get mina - // working, but that brings us into a whole other world of classloading and shading pain. Because - // Forge excludes everything under org.apache.*? Is that true? Ugh, FIXME. - // This all works perfectly fine with Fabric. :( - - - //https://stackoverflow.com/questions/67767455/setting-ssh-keys-to-use-with-jgit-with-ssh-from-apache-sshd - //https://www.eclipse.org/forums/index.php/t/1107487/ - //https://github.com/AzBuilder/terrakube/blob/67f992c84cb2f66ce17a2e2ab85796872429720b/api/src/main/java/org/terrakube/api/plugin/ssh/TerrakubeSshdSessionFactory.java#L6 - - //https://stackoverflow.com/questions/65566138/apache-mina-sshd-ssh-client-always-prints-eddsa-provider-not-supported - //If you don't fix this, then you will not be able to validate the host keys. My testing was not impacted because I was not validating the host keys yet. However, once deployed to production, I would have been impacted because host keys must be validated. - //https://dzone.com/articles/jgit-library-examples-in-java - - //SecurityUtils.setDefaultProviderChoice(new EdDSASecurityProviderRegistrar()); - - /** - String CLAZZ = EdDSASecurityProviderRegistrar.class.getNa this.lifecycleListener.onInitialize(); - me();//"net.pcal.fastback.relocated.org.apache.sshd.common.util.security.eddsa.EdDSASecurityProviderRegistrar"; - syslog().warn("!!!! "+CLAZZ); - try { - Class.forName(CLAZZ); - } catch (ClassNotFoundException e) { - syslog().error(new RuntimeException(e)); - } - System.setProperty("org.apache.sshd.security.registrars", CLAZZ); - **/ -// - - - /** - * - then we can try this, but i'm having a heck of a time getting the i2p provider to load >:( - if (false) { - File sshDir = new File(FS.DETECTED.userHome(), "/.ssh"); - - SshdSessionFactory sshSessionFactory = new SshdSessionFactoryBuilder() - .setPreferredAuthentications("publickey") - .setHomeDirectory(FS.DETECTED.userHome()) - .setSshDirectory(sshDir) - - .setServerKeyDatabase((h, s) -> new ServerKeyDatabase() { - - @Override public List lookup(String connectAddress, - InetSocketAddress remoteAddress, - Configuration config) { - return Collections.emptyList(); - } - - @Override public boolean accept(String connectAddress, - InetSocketAddress remoteAddress, - PublicKey serverKey, Configuration config, - CredentialsProvider provider) { - return true; - } - - }) - .build(new JGitKeyCache()); - SshSessionFactory.setInstance(sshSessionFactory); - } - **/ - /** - - //SshdSessionFactory factory = new SshdSessionFactory(new JGitKeyCache(), new DefaultProxyDataFactory()); - SshdSessionFactory factory = new SshdSessionFactory(); - try { - Runtime.getRuntime() - .addShutdownHook(new Thread(factory::close)); - } catch (IllegalStateException e) { - // ignore - the VM is already shutting down - } - SshSessionFactory.setInstance(factory); - - - } - **/ -}