I am attempting to get an embedded Spring Config Server implementation working that reads configuration from GitHub. I'm following this tutorial:
https://mromeh.com/2017/12/04/spring-boot-with-embedded-config-server-via-spring-cloud-config/
I am getting the following Exception when my Spring Boot app tries to start up:
Caused by: com.jcraft.jsch.JSchException: There are not any available ciphers. at com.jcraft.jsch.Session.send_kexinit(Session.java:629) at com.jcraft.jsch.Session.connect(Session.java:307) at org.eclipse.jgit.transport.JschConfigSessionFactory.getSession(JschConfigSessionFactory.java:146) ... 23 more
The only interesting bit in my code that I see contributing to this is my bootstrap.yml
file, which looks like this:
spring:
application:
name: DemoApplication.yml
---
spring:
cloud:
config:
failFast: true
server:
bootstrap: true
git:
uri: [email protected]:mycompany/demo-config.git
I am running OpenJDK 8 v212 on MacOS, per running the following:
#> java -version
openjdk version "1.8.0_212"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_212-b03)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.212-b03, mixed mode)
I've searched through the Spring code and documentation, and have yet to find anything about passing configuration parameters or adding code to affect how the Jsch session being used by Spring is constructed. Everything I find suggests that what I'm doing should just work.
I'm at a loss as to where to go from here. Can someone tell me what I'm missing...what I need to do to get past this problem?
To consolidate the comments earlier...
Behind the scenes, Spring is using JGit to make the SSH connection. By default this uses JSch to make the SSH connection, which is configured by the ~/.ssh/config
file.
The wiki also has details of how to bypass JSch and use a native ssh
command, the GIT_SSH
environment variable can be set, e.g. to /usr/bin/ssh
in OS X or Linux, or even something like C:\Program Files\TortoiseGit\bin\TortoiseGitPlink.exe
.
Following the comment about how to avoid a dependency on setting the environment variable, note how the GIT_SSH
environment variable is checked using a SystemReader
in the TransportGitSsh.useExtSession() method.
This means one way would be to override the SystemReader
class. It's not a small interface though, so would involve a fair bit of wrapping code - with the custom bit in getenv()
:
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.SystemReader;
public class CustomSystemReader extends SystemReader {
private final SystemReader systemReader;
public CustomSystemReader(SystemReader systemReader) {
this.systemReader = systemReader;
}
@Override
public String getHostname() {
return systemReader.getHostname();
}
@Override
public String getenv(String variable) {
if ("GIT_SSH".equals(variable))
return "/usr/bin/ssh";
return systemReader.getenv(variable);
}
@Override
public String getProperty(String key) {
return systemReader.getProperty(key);
}
@Override
public FileBasedConfig openUserConfig(Config parent, FS fs) {
return systemReader.openUserConfig(parent, fs);
}
@Override
public FileBasedConfig openSystemConfig(Config parent, FS fs) {
return systemReader.openSystemConfig(parent, fs);
}
@Override
public long getCurrentTime() {
return systemReader.getCurrentTime();
}
@Override
public int getTimezone(long when) {
return systemReader.getTimezone(when);
}
}
Which can then be wired in like this:
SystemReader.setInstance(
new CustomSystemReader(SystemReader.getInstance()));